@techdocs/cli 1.9.8-next.0 → 1.9.8

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 (922) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/embedded-app/.config-schema.json +91 -46
  3. package/dist/embedded-app/index.html +1 -1
  4. package/dist/embedded-app/index.html.tmpl +1 -1
  5. package/dist/embedded-app/static/1029.4e515550.chunk.js +2 -0
  6. package/dist/embedded-app/static/1029.4e515550.chunk.js.map +1 -0
  7. package/dist/embedded-app/static/1361.7604740c.chunk.js +2 -0
  8. package/dist/embedded-app/static/1361.7604740c.chunk.js.map +1 -0
  9. package/dist/embedded-app/static/1479.5beef444.chunk.js +2 -0
  10. package/dist/embedded-app/static/1479.5beef444.chunk.js.map +1 -0
  11. package/dist/embedded-app/static/1513.8f1bc575.chunk.js +2 -0
  12. package/dist/embedded-app/static/1513.8f1bc575.chunk.js.map +1 -0
  13. package/dist/embedded-app/static/2686.ef2fd651.chunk.js +8 -0
  14. package/dist/embedded-app/static/2686.ef2fd651.chunk.js.map +1 -0
  15. package/dist/embedded-app/static/2695.e50c100b.chunk.js +2 -0
  16. package/dist/embedded-app/static/2695.e50c100b.chunk.js.map +1 -0
  17. package/dist/embedded-app/static/3058.4fcf00d8.chunk.js +10 -0
  18. package/dist/embedded-app/static/3058.4fcf00d8.chunk.js.map +1 -0
  19. package/dist/embedded-app/static/3072.6fcf1a5f.chunk.js +2 -0
  20. package/dist/embedded-app/static/3072.6fcf1a5f.chunk.js.map +1 -0
  21. package/dist/embedded-app/static/4142.696247f3.chunk.js +2 -0
  22. package/dist/embedded-app/static/4142.696247f3.chunk.js.map +1 -0
  23. package/dist/embedded-app/static/4217.4e492f57.chunk.js +2 -0
  24. package/dist/embedded-app/static/4217.4e492f57.chunk.js.map +1 -0
  25. package/dist/embedded-app/static/4446.bb0c3080.chunk.js +2 -0
  26. package/dist/embedded-app/static/4446.bb0c3080.chunk.js.map +1 -0
  27. package/dist/embedded-app/static/5526.25e08a28.chunk.js +2 -0
  28. package/dist/embedded-app/static/5526.25e08a28.chunk.js.map +1 -0
  29. package/dist/embedded-app/static/6333.0782515a.chunk.js +2 -0
  30. package/dist/embedded-app/static/6333.0782515a.chunk.js.map +1 -0
  31. package/dist/embedded-app/static/6356.7704dc79.chunk.js +2 -0
  32. package/dist/embedded-app/static/6356.7704dc79.chunk.js.map +1 -0
  33. package/dist/embedded-app/static/73.20ff1e8c.chunk.js +2 -0
  34. package/dist/embedded-app/static/73.20ff1e8c.chunk.js.map +1 -0
  35. package/dist/embedded-app/static/763.7f013a6c.chunk.js +2 -0
  36. package/dist/embedded-app/static/763.7f013a6c.chunk.js.map +1 -0
  37. package/dist/embedded-app/static/7952.8477042e.chunk.js +2 -0
  38. package/dist/embedded-app/static/7952.8477042e.chunk.js.map +1 -0
  39. package/dist/embedded-app/static/7996.2d5c466a.chunk.js +7 -0
  40. package/dist/embedded-app/static/7996.2d5c466a.chunk.js.map +1 -0
  41. package/dist/embedded-app/static/8111.a06e9408.chunk.js +2 -0
  42. package/dist/embedded-app/static/8111.a06e9408.chunk.js.map +1 -0
  43. package/dist/embedded-app/static/8189.e92b520c.chunk.js +2 -0
  44. package/dist/embedded-app/static/8189.e92b520c.chunk.js.map +1 -0
  45. package/dist/embedded-app/static/8403.3a64a455.chunk.js +2 -0
  46. package/dist/embedded-app/static/8403.3a64a455.chunk.js.map +1 -0
  47. package/dist/embedded-app/static/843.f00633b3.chunk.js +5 -0
  48. package/dist/embedded-app/static/843.f00633b3.chunk.js.map +1 -0
  49. package/dist/embedded-app/static/8827.13c65dc1.chunk.js +2 -0
  50. package/dist/embedded-app/static/8827.13c65dc1.chunk.js.map +1 -0
  51. package/dist/embedded-app/static/9787.69e6d4de.chunk.js +2 -0
  52. package/dist/embedded-app/static/9787.69e6d4de.chunk.js.map +1 -0
  53. package/dist/embedded-app/static/main.65c066bf.js +550 -0
  54. package/dist/embedded-app/static/main.65c066bf.js.map +1 -0
  55. package/dist/embedded-app/static/module-date-fns.0117079c.js +2 -0
  56. package/dist/embedded-app/static/module-date-fns.0117079c.js.map +1 -0
  57. package/dist/embedded-app/static/module-i18next.93181ae4.js +2 -0
  58. package/dist/embedded-app/static/module-i18next.93181ae4.js.map +1 -0
  59. package/dist/embedded-app/static/module-lodash.011b7e00.js +2 -0
  60. package/dist/embedded-app/static/module-lodash.011b7e00.js.map +1 -0
  61. package/dist/embedded-app/static/module-material-table.fb5299bb.js +2 -0
  62. package/dist/embedded-app/static/module-material-table.fb5299bb.js.map +1 -0
  63. package/dist/embedded-app/static/module-material-ui.d59b3501.js +2 -0
  64. package/dist/embedded-app/static/module-material-ui.d59b3501.js.map +1 -0
  65. package/dist/embedded-app/static/module-mui.642fff5d.js +2 -0
  66. package/dist/embedded-app/static/module-mui.642fff5d.js.map +1 -0
  67. package/dist/embedded-app/static/module-react-beautiful-dnd.4021175e.js +2 -0
  68. package/dist/embedded-app/static/module-react-beautiful-dnd.4021175e.js.map +1 -0
  69. package/dist/embedded-app/static/module-react-dom.e3032225.js +2 -0
  70. package/dist/embedded-app/static/module-react-dom.e3032225.js.map +1 -0
  71. package/dist/embedded-app/static/module-remix-run.df99de31.js +2 -0
  72. package/dist/embedded-app/static/module-remix-run.df99de31.js.map +1 -0
  73. package/dist/embedded-app/static/module-zod.76c8aba2.js +2 -0
  74. package/dist/embedded-app/static/module-zod.76c8aba2.js.map +1 -0
  75. package/dist/embedded-app/static/react-syntax-highlighter/lowlight-import.35bdc6fd.chunk.js +2 -0
  76. package/dist/embedded-app/static/react-syntax-highlighter/lowlight-import.35bdc6fd.chunk.js.map +1 -0
  77. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_abnf.af1d2097.chunk.js +2 -0
  78. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_abnf.af1d2097.chunk.js.map +1 -0
  79. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_accesslog.0f6dfc0c.chunk.js +2 -0
  80. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_accesslog.0f6dfc0c.chunk.js.map +1 -0
  81. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_actionscript.a7fb64f6.chunk.js +2 -0
  82. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_actionscript.a7fb64f6.chunk.js.map +1 -0
  83. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ada.6d68ba98.chunk.js +2 -0
  84. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ada.6d68ba98.chunk.js.map +1 -0
  85. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_angelscript.5baaa70f.chunk.js +2 -0
  86. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_angelscript.5baaa70f.chunk.js.map +1 -0
  87. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_apache.4097a85c.chunk.js +2 -0
  88. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_apache.4097a85c.chunk.js.map +1 -0
  89. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_applescript.c270ec00.chunk.js +2 -0
  90. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_applescript.c270ec00.chunk.js.map +1 -0
  91. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_arcade.7dadf670.chunk.js +2 -0
  92. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_arcade.7dadf670.chunk.js.map +1 -0
  93. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_arduino.8a2e554a.chunk.js +2 -0
  94. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_arduino.8a2e554a.chunk.js.map +1 -0
  95. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_armasm.0eedca34.chunk.js +2 -0
  96. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_armasm.0eedca34.chunk.js.map +1 -0
  97. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_asciidoc.cd08330d.chunk.js +2 -0
  98. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_asciidoc.cd08330d.chunk.js.map +1 -0
  99. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_aspectj.d1a17b25.chunk.js +2 -0
  100. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_aspectj.d1a17b25.chunk.js.map +1 -0
  101. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_autohotkey.f8064fb0.chunk.js +2 -0
  102. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_autohotkey.f8064fb0.chunk.js.map +1 -0
  103. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_autoit.bae01d42.chunk.js +2 -0
  104. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_autoit.bae01d42.chunk.js.map +1 -0
  105. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_avrasm.97ac5f19.chunk.js +2 -0
  106. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_avrasm.97ac5f19.chunk.js.map +1 -0
  107. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_awk.6e4fa357.chunk.js +2 -0
  108. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_awk.6e4fa357.chunk.js.map +1 -0
  109. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_axapta.c823f597.chunk.js +2 -0
  110. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_axapta.c823f597.chunk.js.map +1 -0
  111. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_bash.dd94d803.chunk.js +2 -0
  112. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_bash.dd94d803.chunk.js.map +1 -0
  113. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_basic.a2c8620b.chunk.js +2 -0
  114. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_basic.a2c8620b.chunk.js.map +1 -0
  115. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_bnf.0efb110b.chunk.js +2 -0
  116. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_bnf.0efb110b.chunk.js.map +1 -0
  117. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_brainfuck.b391d999.chunk.js +2 -0
  118. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_brainfuck.b391d999.chunk.js.map +1 -0
  119. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_c.9af2a593.chunk.js +2 -0
  120. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_c.9af2a593.chunk.js.map +1 -0
  121. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cLike.bc296b3b.chunk.js +2 -0
  122. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cLike.bc296b3b.chunk.js.map +1 -0
  123. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cal.0f6e1bfc.chunk.js +2 -0
  124. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cal.0f6e1bfc.chunk.js.map +1 -0
  125. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_capnproto.0b1da46b.chunk.js +2 -0
  126. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_capnproto.0b1da46b.chunk.js.map +1 -0
  127. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ceylon.a0558c77.chunk.js +2 -0
  128. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ceylon.a0558c77.chunk.js.map +1 -0
  129. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_clean.9f770be6.chunk.js +2 -0
  130. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_clean.9f770be6.chunk.js.map +1 -0
  131. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_clojure.8bcc1abd.chunk.js +2 -0
  132. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_clojure.8bcc1abd.chunk.js.map +1 -0
  133. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_clojureRepl.09c54cbd.chunk.js +2 -0
  134. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_clojureRepl.09c54cbd.chunk.js.map +1 -0
  135. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cmake.daea3ad5.chunk.js +2 -0
  136. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cmake.daea3ad5.chunk.js.map +1 -0
  137. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_coffeescript.23b3a153.chunk.js +2 -0
  138. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_coffeescript.23b3a153.chunk.js.map +1 -0
  139. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_coq.b578ed0b.chunk.js +2 -0
  140. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_coq.b578ed0b.chunk.js.map +1 -0
  141. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cos.26fb9b5f.chunk.js +2 -0
  142. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cos.26fb9b5f.chunk.js.map +1 -0
  143. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cpp.7131bfa5.chunk.js +2 -0
  144. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cpp.7131bfa5.chunk.js.map +1 -0
  145. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_crmsh.43fb29d9.chunk.js +2 -0
  146. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_crmsh.43fb29d9.chunk.js.map +1 -0
  147. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_crystal.1a483e2e.chunk.js +2 -0
  148. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_crystal.1a483e2e.chunk.js.map +1 -0
  149. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_csharp.cd92a328.chunk.js +2 -0
  150. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_csharp.cd92a328.chunk.js.map +1 -0
  151. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_csp.686bf8aa.chunk.js +2 -0
  152. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_csp.686bf8aa.chunk.js.map +1 -0
  153. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_css.ec2048bd.chunk.js +2 -0
  154. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_css.ec2048bd.chunk.js.map +1 -0
  155. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_d.6988fc39.chunk.js +2 -0
  156. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_d.6988fc39.chunk.js.map +1 -0
  157. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dart.e8b0aa12.chunk.js +2 -0
  158. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dart.e8b0aa12.chunk.js.map +1 -0
  159. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_delphi.42fde874.chunk.js +2 -0
  160. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_delphi.42fde874.chunk.js.map +1 -0
  161. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_diff.9f071c57.chunk.js +2 -0
  162. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_diff.9f071c57.chunk.js.map +1 -0
  163. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_django.65fa15f8.chunk.js +2 -0
  164. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_django.65fa15f8.chunk.js.map +1 -0
  165. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dns.9ad54f17.chunk.js +2 -0
  166. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dns.9ad54f17.chunk.js.map +1 -0
  167. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dockerfile.3c23a625.chunk.js +2 -0
  168. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dockerfile.3c23a625.chunk.js.map +1 -0
  169. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dos.b3be7221.chunk.js +2 -0
  170. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dos.b3be7221.chunk.js.map +1 -0
  171. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dsconfig.10886f3a.chunk.js +2 -0
  172. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dsconfig.10886f3a.chunk.js.map +1 -0
  173. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dts.959615f5.chunk.js +2 -0
  174. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dts.959615f5.chunk.js.map +1 -0
  175. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dust.506de762.chunk.js +2 -0
  176. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dust.506de762.chunk.js.map +1 -0
  177. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ebnf.331b7238.chunk.js +2 -0
  178. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ebnf.331b7238.chunk.js.map +1 -0
  179. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_elixir.114be8d1.chunk.js +2 -0
  180. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_elixir.114be8d1.chunk.js.map +1 -0
  181. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_elm.015946b0.chunk.js +2 -0
  182. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_elm.015946b0.chunk.js.map +1 -0
  183. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_erb.13958520.chunk.js +2 -0
  184. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_erb.13958520.chunk.js.map +1 -0
  185. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_erlang.059ec9a2.chunk.js +2 -0
  186. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_erlang.059ec9a2.chunk.js.map +1 -0
  187. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_erlangRepl.b1989ae8.chunk.js +2 -0
  188. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_erlangRepl.b1989ae8.chunk.js.map +1 -0
  189. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_excel.c345f8a6.chunk.js +2 -0
  190. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_excel.c345f8a6.chunk.js.map +1 -0
  191. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_fix.997bdf52.chunk.js +2 -0
  192. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_fix.997bdf52.chunk.js.map +1 -0
  193. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_flix.8912374a.chunk.js +2 -0
  194. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_flix.8912374a.chunk.js.map +1 -0
  195. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_fortran.c5f8658a.chunk.js +2 -0
  196. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_fortran.c5f8658a.chunk.js.map +1 -0
  197. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_fsharp.ed4dfab0.chunk.js +2 -0
  198. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_fsharp.ed4dfab0.chunk.js.map +1 -0
  199. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gams.87ed0fbd.chunk.js +2 -0
  200. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gams.87ed0fbd.chunk.js.map +1 -0
  201. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gauss.d1e7f0c3.chunk.js +2 -0
  202. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gauss.d1e7f0c3.chunk.js.map +1 -0
  203. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gcode.b252367c.chunk.js +2 -0
  204. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gcode.b252367c.chunk.js.map +1 -0
  205. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gherkin.9dd00540.chunk.js +2 -0
  206. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gherkin.9dd00540.chunk.js.map +1 -0
  207. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_glsl.e61ec03b.chunk.js +2 -0
  208. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_glsl.e61ec03b.chunk.js.map +1 -0
  209. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gml.58a3bcf7.chunk.js +2 -0
  210. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gml.58a3bcf7.chunk.js.map +1 -0
  211. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_go.bc66da31.chunk.js +2 -0
  212. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_go.bc66da31.chunk.js.map +1 -0
  213. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_golo.c89d56cd.chunk.js +2 -0
  214. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_golo.c89d56cd.chunk.js.map +1 -0
  215. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gradle.b95dc02b.chunk.js +2 -0
  216. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gradle.b95dc02b.chunk.js.map +1 -0
  217. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_groovy.77e0fd86.chunk.js +2 -0
  218. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_groovy.77e0fd86.chunk.js.map +1 -0
  219. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_haml.aa4081ea.chunk.js +2 -0
  220. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_haml.aa4081ea.chunk.js.map +1 -0
  221. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_handlebars.b0800b1a.chunk.js +2 -0
  222. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_handlebars.b0800b1a.chunk.js.map +1 -0
  223. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_haskell.4cdc46ba.chunk.js +2 -0
  224. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_haskell.4cdc46ba.chunk.js.map +1 -0
  225. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_haxe.11d1ada7.chunk.js +2 -0
  226. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_haxe.11d1ada7.chunk.js.map +1 -0
  227. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_hsp.a0a21baf.chunk.js +2 -0
  228. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_hsp.a0a21baf.chunk.js.map +1 -0
  229. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_htmlbars.4f7630ce.chunk.js +2 -0
  230. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_htmlbars.4f7630ce.chunk.js.map +1 -0
  231. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_http.ebcd7d52.chunk.js +2 -0
  232. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_http.ebcd7d52.chunk.js.map +1 -0
  233. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_hy.7a4bd03b.chunk.js +2 -0
  234. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_hy.7a4bd03b.chunk.js.map +1 -0
  235. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_inform7.d63139cd.chunk.js +2 -0
  236. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_inform7.d63139cd.chunk.js.map +1 -0
  237. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ini.bc2cd76e.chunk.js +2 -0
  238. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ini.bc2cd76e.chunk.js.map +1 -0
  239. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_irpf90.5f3dea5a.chunk.js +2 -0
  240. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_irpf90.5f3dea5a.chunk.js.map +1 -0
  241. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_isbl.98aa970e.chunk.js +2 -0
  242. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_isbl.98aa970e.chunk.js.map +1 -0
  243. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_java.1744f314.chunk.js +2 -0
  244. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_java.1744f314.chunk.js.map +1 -0
  245. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_javascript.eb990041.chunk.js +2 -0
  246. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_javascript.eb990041.chunk.js.map +1 -0
  247. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_jbossCli.4938e069.chunk.js +2 -0
  248. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_jbossCli.4938e069.chunk.js.map +1 -0
  249. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_json.eeb74256.chunk.js +2 -0
  250. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_json.eeb74256.chunk.js.map +1 -0
  251. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_julia.3b10dc5f.chunk.js +2 -0
  252. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_julia.3b10dc5f.chunk.js.map +1 -0
  253. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_juliaRepl.3bb4a4e7.chunk.js +2 -0
  254. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_juliaRepl.3bb4a4e7.chunk.js.map +1 -0
  255. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_kotlin.e0d91f8a.chunk.js +2 -0
  256. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_kotlin.e0d91f8a.chunk.js.map +1 -0
  257. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_lasso.5c398672.chunk.js +2 -0
  258. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_lasso.5c398672.chunk.js.map +1 -0
  259. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_latex.9d2c283d.chunk.js +2 -0
  260. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_latex.9d2c283d.chunk.js.map +1 -0
  261. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ldif.d7168107.chunk.js +2 -0
  262. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ldif.d7168107.chunk.js.map +1 -0
  263. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_leaf.008e2d1d.chunk.js +2 -0
  264. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_leaf.008e2d1d.chunk.js.map +1 -0
  265. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_less.2de4a4fe.chunk.js +2 -0
  266. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_less.2de4a4fe.chunk.js.map +1 -0
  267. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_lisp.511baec8.chunk.js +2 -0
  268. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_lisp.511baec8.chunk.js.map +1 -0
  269. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_livecodeserver.1bf3226c.chunk.js +2 -0
  270. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_livecodeserver.1bf3226c.chunk.js.map +1 -0
  271. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_livescript.bd04ac2c.chunk.js +2 -0
  272. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_livescript.bd04ac2c.chunk.js.map +1 -0
  273. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_llvm.bfbf2be1.chunk.js +2 -0
  274. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_llvm.bfbf2be1.chunk.js.map +1 -0
  275. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_lsl.4646ce68.chunk.js +2 -0
  276. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_lsl.4646ce68.chunk.js.map +1 -0
  277. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_lua.0f38cb73.chunk.js +2 -0
  278. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_lua.0f38cb73.chunk.js.map +1 -0
  279. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_makefile.22028765.chunk.js +2 -0
  280. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_makefile.22028765.chunk.js.map +1 -0
  281. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_markdown.e5a3a7ce.chunk.js +2 -0
  282. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_markdown.e5a3a7ce.chunk.js.map +1 -0
  283. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mathematica.2f818d43.chunk.js +2 -0
  284. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mathematica.2f818d43.chunk.js.map +1 -0
  285. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_matlab.180e1164.chunk.js +2 -0
  286. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_matlab.180e1164.chunk.js.map +1 -0
  287. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_maxima.89253d5c.chunk.js +2 -0
  288. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_maxima.89253d5c.chunk.js.map +1 -0
  289. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mel.a4013f74.chunk.js +2 -0
  290. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mel.a4013f74.chunk.js.map +1 -0
  291. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mercury.54311887.chunk.js +2 -0
  292. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mercury.54311887.chunk.js.map +1 -0
  293. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mipsasm.ab47f45f.chunk.js +2 -0
  294. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mipsasm.ab47f45f.chunk.js.map +1 -0
  295. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mizar.2081ab77.chunk.js +2 -0
  296. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mizar.2081ab77.chunk.js.map +1 -0
  297. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mojolicious.1613ed5f.chunk.js +2 -0
  298. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mojolicious.1613ed5f.chunk.js.map +1 -0
  299. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_monkey.96bfad5e.chunk.js +2 -0
  300. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_monkey.96bfad5e.chunk.js.map +1 -0
  301. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_moonscript.5bba0736.chunk.js +2 -0
  302. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_moonscript.5bba0736.chunk.js.map +1 -0
  303. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_n1ql.2d47ae87.chunk.js +2 -0
  304. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_n1ql.2d47ae87.chunk.js.map +1 -0
  305. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nginx.40293eda.chunk.js +2 -0
  306. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nginx.40293eda.chunk.js.map +1 -0
  307. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nim.faa55b31.chunk.js +2 -0
  308. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nim.faa55b31.chunk.js.map +1 -0
  309. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nix.1cdcecae.chunk.js +2 -0
  310. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nix.1cdcecae.chunk.js.map +1 -0
  311. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nodeRepl.f123557e.chunk.js +2 -0
  312. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nodeRepl.f123557e.chunk.js.map +1 -0
  313. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nsis.4c4909c6.chunk.js +2 -0
  314. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nsis.4c4909c6.chunk.js.map +1 -0
  315. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_objectivec.7bd7d9ec.chunk.js +2 -0
  316. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_objectivec.7bd7d9ec.chunk.js.map +1 -0
  317. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ocaml.720d1d85.chunk.js +2 -0
  318. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ocaml.720d1d85.chunk.js.map +1 -0
  319. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_oneC.c05ded1a.chunk.js +2 -0
  320. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_oneC.c05ded1a.chunk.js.map +1 -0
  321. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_openscad.3210f8ea.chunk.js +2 -0
  322. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_openscad.3210f8ea.chunk.js.map +1 -0
  323. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_oxygene.8c863244.chunk.js +2 -0
  324. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_oxygene.8c863244.chunk.js.map +1 -0
  325. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_parser3.83eff03e.chunk.js +2 -0
  326. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_parser3.83eff03e.chunk.js.map +1 -0
  327. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_perl.ab1ea27f.chunk.js +2 -0
  328. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_perl.ab1ea27f.chunk.js.map +1 -0
  329. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_pf.719059d1.chunk.js +2 -0
  330. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_pf.719059d1.chunk.js.map +1 -0
  331. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_pgsql.59e2f825.chunk.js +2 -0
  332. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_pgsql.59e2f825.chunk.js.map +1 -0
  333. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_php.0a8cc90f.chunk.js +2 -0
  334. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_php.0a8cc90f.chunk.js.map +1 -0
  335. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_phpTemplate.ce2f48cd.chunk.js +2 -0
  336. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_phpTemplate.ce2f48cd.chunk.js.map +1 -0
  337. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_plaintext.7b8ff8cd.chunk.js +2 -0
  338. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_plaintext.7b8ff8cd.chunk.js.map +1 -0
  339. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_pony.4dac5429.chunk.js +2 -0
  340. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_pony.4dac5429.chunk.js.map +1 -0
  341. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_powershell.c6714eb0.chunk.js +2 -0
  342. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_powershell.c6714eb0.chunk.js.map +1 -0
  343. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_processing.0a5ff9e9.chunk.js +2 -0
  344. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_processing.0a5ff9e9.chunk.js.map +1 -0
  345. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_profile.094be4b5.chunk.js +2 -0
  346. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_profile.094be4b5.chunk.js.map +1 -0
  347. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_prolog.3b8c3a26.chunk.js +2 -0
  348. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_prolog.3b8c3a26.chunk.js.map +1 -0
  349. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_properties.99838fba.chunk.js +2 -0
  350. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_properties.99838fba.chunk.js.map +1 -0
  351. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_protobuf.6a1dd1d5.chunk.js +2 -0
  352. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_protobuf.6a1dd1d5.chunk.js.map +1 -0
  353. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_puppet.1dfc1530.chunk.js +2 -0
  354. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_puppet.1dfc1530.chunk.js.map +1 -0
  355. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_purebasic.bf87c647.chunk.js +2 -0
  356. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_purebasic.bf87c647.chunk.js.map +1 -0
  357. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_python.d2c0c968.chunk.js +2 -0
  358. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_python.d2c0c968.chunk.js.map +1 -0
  359. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_pythonRepl.bb8e2d18.chunk.js +2 -0
  360. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_pythonRepl.bb8e2d18.chunk.js.map +1 -0
  361. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_q.8b1b5268.chunk.js +2 -0
  362. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_q.8b1b5268.chunk.js.map +1 -0
  363. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_qml.732abe09.chunk.js +2 -0
  364. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_qml.732abe09.chunk.js.map +1 -0
  365. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_r.a21f2631.chunk.js +2 -0
  366. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_r.a21f2631.chunk.js.map +1 -0
  367. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_reasonml.fda7458b.chunk.js +2 -0
  368. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_reasonml.fda7458b.chunk.js.map +1 -0
  369. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_rib.dc23d97e.chunk.js +2 -0
  370. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_rib.dc23d97e.chunk.js.map +1 -0
  371. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_roboconf.62556006.chunk.js +2 -0
  372. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_roboconf.62556006.chunk.js.map +1 -0
  373. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_routeros.74a7d01a.chunk.js +2 -0
  374. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_routeros.74a7d01a.chunk.js.map +1 -0
  375. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_rsl.a06dcc6e.chunk.js +2 -0
  376. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_rsl.a06dcc6e.chunk.js.map +1 -0
  377. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ruby.1cb86063.chunk.js +2 -0
  378. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ruby.1cb86063.chunk.js.map +1 -0
  379. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ruleslanguage.0c6fd080.chunk.js +2 -0
  380. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ruleslanguage.0c6fd080.chunk.js.map +1 -0
  381. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_rust.625421e9.chunk.js +2 -0
  382. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_rust.625421e9.chunk.js.map +1 -0
  383. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sas.a90c3439.chunk.js +2 -0
  384. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sas.a90c3439.chunk.js.map +1 -0
  385. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_scala.f2664b1b.chunk.js +2 -0
  386. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_scala.f2664b1b.chunk.js.map +1 -0
  387. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_scheme.c719e09d.chunk.js +2 -0
  388. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_scheme.c719e09d.chunk.js.map +1 -0
  389. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_scilab.94868725.chunk.js +2 -0
  390. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_scilab.94868725.chunk.js.map +1 -0
  391. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_scss.d1bbf68a.chunk.js +2 -0
  392. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_scss.d1bbf68a.chunk.js.map +1 -0
  393. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_shell.314afd8d.chunk.js +2 -0
  394. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_shell.314afd8d.chunk.js.map +1 -0
  395. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_smali.1e8fc6ef.chunk.js +2 -0
  396. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_smali.1e8fc6ef.chunk.js.map +1 -0
  397. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_smalltalk.fbee4a63.chunk.js +2 -0
  398. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_smalltalk.fbee4a63.chunk.js.map +1 -0
  399. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sml.2d2b3bc0.chunk.js +2 -0
  400. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sml.2d2b3bc0.chunk.js.map +1 -0
  401. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sqf.3434c40a.chunk.js +2 -0
  402. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sqf.3434c40a.chunk.js.map +1 -0
  403. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sql.0a2bc665.chunk.js +2 -0
  404. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sql.0a2bc665.chunk.js.map +1 -0
  405. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sqlMore.d851f049.chunk.js +2 -0
  406. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sqlMore.d851f049.chunk.js.map +1 -0
  407. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_stan.ec9db1dd.chunk.js +2 -0
  408. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_stan.ec9db1dd.chunk.js.map +1 -0
  409. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_stata.8e8425e3.chunk.js +2 -0
  410. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_stata.8e8425e3.chunk.js.map +1 -0
  411. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_step21.38efb9fb.chunk.js +2 -0
  412. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_step21.38efb9fb.chunk.js.map +1 -0
  413. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_stylus.cbd9303a.chunk.js +2 -0
  414. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_stylus.cbd9303a.chunk.js.map +1 -0
  415. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_subunit.fd37b65b.chunk.js +2 -0
  416. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_subunit.fd37b65b.chunk.js.map +1 -0
  417. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_swift.9ad73bf2.chunk.js +2 -0
  418. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_swift.9ad73bf2.chunk.js.map +1 -0
  419. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_taggerscript.84d234b2.chunk.js +2 -0
  420. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_taggerscript.84d234b2.chunk.js.map +1 -0
  421. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_tap.6fc8e790.chunk.js +2 -0
  422. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_tap.6fc8e790.chunk.js.map +1 -0
  423. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_tcl.9fcb43d8.chunk.js +2 -0
  424. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_tcl.9fcb43d8.chunk.js.map +1 -0
  425. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_thrift.d49c707a.chunk.js +2 -0
  426. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_thrift.d49c707a.chunk.js.map +1 -0
  427. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_tp.db9715f9.chunk.js +2 -0
  428. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_tp.db9715f9.chunk.js.map +1 -0
  429. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_twig.78290e2a.chunk.js +2 -0
  430. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_twig.78290e2a.chunk.js.map +1 -0
  431. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_typescript.00824c6b.chunk.js +2 -0
  432. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_typescript.00824c6b.chunk.js.map +1 -0
  433. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vala.228b5503.chunk.js +2 -0
  434. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vala.228b5503.chunk.js.map +1 -0
  435. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vbnet.81ff4902.chunk.js +2 -0
  436. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vbnet.81ff4902.chunk.js.map +1 -0
  437. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vbscript.33c9b8d6.chunk.js +2 -0
  438. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vbscript.33c9b8d6.chunk.js.map +1 -0
  439. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vbscriptHtml.90d51346.chunk.js +2 -0
  440. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vbscriptHtml.90d51346.chunk.js.map +1 -0
  441. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_verilog.0ee01e3e.chunk.js +2 -0
  442. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_verilog.0ee01e3e.chunk.js.map +1 -0
  443. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vhdl.ddd2d5fa.chunk.js +2 -0
  444. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vhdl.ddd2d5fa.chunk.js.map +1 -0
  445. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vim.cd6abc97.chunk.js +2 -0
  446. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vim.cd6abc97.chunk.js.map +1 -0
  447. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_x86asm.7f2b3235.chunk.js +2 -0
  448. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_x86asm.7f2b3235.chunk.js.map +1 -0
  449. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_xl.0ff3c361.chunk.js +2 -0
  450. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_xl.0ff3c361.chunk.js.map +1 -0
  451. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_xml.8f555890.chunk.js +2 -0
  452. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_xml.8f555890.chunk.js.map +1 -0
  453. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_xquery.6fe6d801.chunk.js +2 -0
  454. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_xquery.6fe6d801.chunk.js.map +1 -0
  455. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_yaml.7d72570c.chunk.js +2 -0
  456. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_yaml.7d72570c.chunk.js.map +1 -0
  457. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_zephir.c69cf0ab.chunk.js +2 -0
  458. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_zephir.c69cf0ab.chunk.js.map +1 -0
  459. package/dist/embedded-app/static/runtime.5e0f3509.js +2 -0
  460. package/dist/embedded-app/static/runtime.5e0f3509.js.map +1 -0
  461. package/dist/embedded-app/static/vendor.4f2223d6.js +2 -0
  462. package/dist/embedded-app/static/vendor.4f2223d6.js.map +1 -0
  463. package/dist/package.json.cjs.js +1 -1
  464. package/package.json +7 -7
  465. package/dist/embedded-app/static/1029.3840e700.chunk.js +0 -2
  466. package/dist/embedded-app/static/1029.3840e700.chunk.js.map +0 -1
  467. package/dist/embedded-app/static/1361.f28eed89.chunk.js +0 -2
  468. package/dist/embedded-app/static/1361.f28eed89.chunk.js.map +0 -1
  469. package/dist/embedded-app/static/1479.989b72ee.chunk.js +0 -2
  470. package/dist/embedded-app/static/1479.989b72ee.chunk.js.map +0 -1
  471. package/dist/embedded-app/static/1513.44ec60bd.chunk.js +0 -2
  472. package/dist/embedded-app/static/1513.44ec60bd.chunk.js.map +0 -1
  473. package/dist/embedded-app/static/2686.4768c08e.chunk.js +0 -8
  474. package/dist/embedded-app/static/2686.4768c08e.chunk.js.map +0 -1
  475. package/dist/embedded-app/static/2695.5598721e.chunk.js +0 -2
  476. package/dist/embedded-app/static/2695.5598721e.chunk.js.map +0 -1
  477. package/dist/embedded-app/static/3058.cacbb2a9.chunk.js +0 -10
  478. package/dist/embedded-app/static/3058.cacbb2a9.chunk.js.map +0 -1
  479. package/dist/embedded-app/static/3072.31f8368b.chunk.js +0 -2
  480. package/dist/embedded-app/static/3072.31f8368b.chunk.js.map +0 -1
  481. package/dist/embedded-app/static/4142.101cd971.chunk.js +0 -2
  482. package/dist/embedded-app/static/4142.101cd971.chunk.js.map +0 -1
  483. package/dist/embedded-app/static/4217.c33738e2.chunk.js +0 -2
  484. package/dist/embedded-app/static/4217.c33738e2.chunk.js.map +0 -1
  485. package/dist/embedded-app/static/4446.83dbf14f.chunk.js +0 -2
  486. package/dist/embedded-app/static/4446.83dbf14f.chunk.js.map +0 -1
  487. package/dist/embedded-app/static/5526.e2d3737b.chunk.js +0 -2
  488. package/dist/embedded-app/static/5526.e2d3737b.chunk.js.map +0 -1
  489. package/dist/embedded-app/static/6333.f59e497b.chunk.js +0 -2
  490. package/dist/embedded-app/static/6333.f59e497b.chunk.js.map +0 -1
  491. package/dist/embedded-app/static/6356.cd772cf4.chunk.js +0 -2
  492. package/dist/embedded-app/static/6356.cd772cf4.chunk.js.map +0 -1
  493. package/dist/embedded-app/static/73.39bb7adc.chunk.js +0 -2
  494. package/dist/embedded-app/static/73.39bb7adc.chunk.js.map +0 -1
  495. package/dist/embedded-app/static/763.2457d9b1.chunk.js +0 -2
  496. package/dist/embedded-app/static/763.2457d9b1.chunk.js.map +0 -1
  497. package/dist/embedded-app/static/7952.d8f6256b.chunk.js +0 -2
  498. package/dist/embedded-app/static/7952.d8f6256b.chunk.js.map +0 -1
  499. package/dist/embedded-app/static/7996.f513fe32.chunk.js +0 -7
  500. package/dist/embedded-app/static/7996.f513fe32.chunk.js.map +0 -1
  501. package/dist/embedded-app/static/8111.4eabed9f.chunk.js +0 -2
  502. package/dist/embedded-app/static/8111.4eabed9f.chunk.js.map +0 -1
  503. package/dist/embedded-app/static/8189.dbe494b6.chunk.js +0 -2
  504. package/dist/embedded-app/static/8189.dbe494b6.chunk.js.map +0 -1
  505. package/dist/embedded-app/static/8403.6b98ea4d.chunk.js +0 -2
  506. package/dist/embedded-app/static/8403.6b98ea4d.chunk.js.map +0 -1
  507. package/dist/embedded-app/static/843.d3cbd5ee.chunk.js +0 -5
  508. package/dist/embedded-app/static/843.d3cbd5ee.chunk.js.map +0 -1
  509. package/dist/embedded-app/static/8827.9b7b07cb.chunk.js +0 -2
  510. package/dist/embedded-app/static/8827.9b7b07cb.chunk.js.map +0 -1
  511. package/dist/embedded-app/static/9787.80f6d5aa.chunk.js +0 -2
  512. package/dist/embedded-app/static/9787.80f6d5aa.chunk.js.map +0 -1
  513. package/dist/embedded-app/static/main.9ead869c.js +0 -550
  514. package/dist/embedded-app/static/main.9ead869c.js.map +0 -1
  515. package/dist/embedded-app/static/module-date-fns.eb783be6.js +0 -2
  516. package/dist/embedded-app/static/module-date-fns.eb783be6.js.map +0 -1
  517. package/dist/embedded-app/static/module-i18next.668ff997.js +0 -2
  518. package/dist/embedded-app/static/module-i18next.668ff997.js.map +0 -1
  519. package/dist/embedded-app/static/module-lodash.9a2c3bdd.js +0 -2
  520. package/dist/embedded-app/static/module-lodash.9a2c3bdd.js.map +0 -1
  521. package/dist/embedded-app/static/module-material-table.82bde846.js +0 -2
  522. package/dist/embedded-app/static/module-material-table.82bde846.js.map +0 -1
  523. package/dist/embedded-app/static/module-material-ui.27b8440e.js +0 -2
  524. package/dist/embedded-app/static/module-material-ui.27b8440e.js.map +0 -1
  525. package/dist/embedded-app/static/module-mui.0878525e.js +0 -2
  526. package/dist/embedded-app/static/module-mui.0878525e.js.map +0 -1
  527. package/dist/embedded-app/static/module-react-beautiful-dnd.d3a32da9.js +0 -2
  528. package/dist/embedded-app/static/module-react-beautiful-dnd.d3a32da9.js.map +0 -1
  529. package/dist/embedded-app/static/module-react-dom.71e2a3dc.js +0 -2
  530. package/dist/embedded-app/static/module-react-dom.71e2a3dc.js.map +0 -1
  531. package/dist/embedded-app/static/module-remix-run.825b4274.js +0 -2
  532. package/dist/embedded-app/static/module-remix-run.825b4274.js.map +0 -1
  533. package/dist/embedded-app/static/module-zod.c6ca20cb.js +0 -2
  534. package/dist/embedded-app/static/module-zod.c6ca20cb.js.map +0 -1
  535. package/dist/embedded-app/static/react-syntax-highlighter/lowlight-import.dd0ef844.chunk.js +0 -2
  536. package/dist/embedded-app/static/react-syntax-highlighter/lowlight-import.dd0ef844.chunk.js.map +0 -1
  537. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_abnf.5a8a0189.chunk.js +0 -2
  538. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_abnf.5a8a0189.chunk.js.map +0 -1
  539. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_accesslog.6ece7943.chunk.js +0 -2
  540. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_accesslog.6ece7943.chunk.js.map +0 -1
  541. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_actionscript.42c6acf3.chunk.js +0 -2
  542. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_actionscript.42c6acf3.chunk.js.map +0 -1
  543. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ada.35e5126d.chunk.js +0 -2
  544. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ada.35e5126d.chunk.js.map +0 -1
  545. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_angelscript.d56b98e2.chunk.js +0 -2
  546. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_angelscript.d56b98e2.chunk.js.map +0 -1
  547. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_apache.0d44f797.chunk.js +0 -2
  548. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_apache.0d44f797.chunk.js.map +0 -1
  549. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_applescript.d68f6f45.chunk.js +0 -2
  550. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_applescript.d68f6f45.chunk.js.map +0 -1
  551. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_arcade.25a95fdd.chunk.js +0 -2
  552. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_arcade.25a95fdd.chunk.js.map +0 -1
  553. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_arduino.a2b6fd58.chunk.js +0 -2
  554. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_arduino.a2b6fd58.chunk.js.map +0 -1
  555. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_armasm.31e67d57.chunk.js +0 -2
  556. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_armasm.31e67d57.chunk.js.map +0 -1
  557. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_asciidoc.e698a15d.chunk.js +0 -2
  558. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_asciidoc.e698a15d.chunk.js.map +0 -1
  559. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_aspectj.0fbeb389.chunk.js +0 -2
  560. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_aspectj.0fbeb389.chunk.js.map +0 -1
  561. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_autohotkey.06c6003f.chunk.js +0 -2
  562. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_autohotkey.06c6003f.chunk.js.map +0 -1
  563. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_autoit.daf38f0c.chunk.js +0 -2
  564. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_autoit.daf38f0c.chunk.js.map +0 -1
  565. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_avrasm.31efe260.chunk.js +0 -2
  566. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_avrasm.31efe260.chunk.js.map +0 -1
  567. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_awk.8e2929bf.chunk.js +0 -2
  568. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_awk.8e2929bf.chunk.js.map +0 -1
  569. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_axapta.264dcd2e.chunk.js +0 -2
  570. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_axapta.264dcd2e.chunk.js.map +0 -1
  571. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_bash.fb740c40.chunk.js +0 -2
  572. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_bash.fb740c40.chunk.js.map +0 -1
  573. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_basic.c282165d.chunk.js +0 -2
  574. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_basic.c282165d.chunk.js.map +0 -1
  575. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_bnf.41e99b51.chunk.js +0 -2
  576. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_bnf.41e99b51.chunk.js.map +0 -1
  577. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_brainfuck.2a9ed738.chunk.js +0 -2
  578. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_brainfuck.2a9ed738.chunk.js.map +0 -1
  579. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_c.7bf336a2.chunk.js +0 -2
  580. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_c.7bf336a2.chunk.js.map +0 -1
  581. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cLike.67dd8f41.chunk.js +0 -2
  582. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cLike.67dd8f41.chunk.js.map +0 -1
  583. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cal.84a1f4bf.chunk.js +0 -2
  584. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cal.84a1f4bf.chunk.js.map +0 -1
  585. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_capnproto.8aa5e1d5.chunk.js +0 -2
  586. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_capnproto.8aa5e1d5.chunk.js.map +0 -1
  587. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ceylon.4406570e.chunk.js +0 -2
  588. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ceylon.4406570e.chunk.js.map +0 -1
  589. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_clean.c182311f.chunk.js +0 -2
  590. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_clean.c182311f.chunk.js.map +0 -1
  591. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_clojure.95dd0ac2.chunk.js +0 -2
  592. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_clojure.95dd0ac2.chunk.js.map +0 -1
  593. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_clojureRepl.caf0887a.chunk.js +0 -2
  594. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_clojureRepl.caf0887a.chunk.js.map +0 -1
  595. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cmake.ea33b265.chunk.js +0 -2
  596. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cmake.ea33b265.chunk.js.map +0 -1
  597. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_coffeescript.06761525.chunk.js +0 -2
  598. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_coffeescript.06761525.chunk.js.map +0 -1
  599. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_coq.5ce27f00.chunk.js +0 -2
  600. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_coq.5ce27f00.chunk.js.map +0 -1
  601. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cos.3448621f.chunk.js +0 -2
  602. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cos.3448621f.chunk.js.map +0 -1
  603. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cpp.dfa1d6dd.chunk.js +0 -2
  604. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_cpp.dfa1d6dd.chunk.js.map +0 -1
  605. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_crmsh.a194ae82.chunk.js +0 -2
  606. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_crmsh.a194ae82.chunk.js.map +0 -1
  607. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_crystal.f3e66f08.chunk.js +0 -2
  608. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_crystal.f3e66f08.chunk.js.map +0 -1
  609. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_csharp.5965b4e2.chunk.js +0 -2
  610. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_csharp.5965b4e2.chunk.js.map +0 -1
  611. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_csp.809ba3bd.chunk.js +0 -2
  612. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_csp.809ba3bd.chunk.js.map +0 -1
  613. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_css.e17bb639.chunk.js +0 -2
  614. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_css.e17bb639.chunk.js.map +0 -1
  615. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_d.e17527f0.chunk.js +0 -2
  616. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_d.e17527f0.chunk.js.map +0 -1
  617. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dart.81b1966d.chunk.js +0 -2
  618. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dart.81b1966d.chunk.js.map +0 -1
  619. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_delphi.dd57a57c.chunk.js +0 -2
  620. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_delphi.dd57a57c.chunk.js.map +0 -1
  621. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_diff.e3ba7a5a.chunk.js +0 -2
  622. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_diff.e3ba7a5a.chunk.js.map +0 -1
  623. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_django.b999aa23.chunk.js +0 -2
  624. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_django.b999aa23.chunk.js.map +0 -1
  625. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dns.42233b3a.chunk.js +0 -2
  626. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dns.42233b3a.chunk.js.map +0 -1
  627. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dockerfile.c5391872.chunk.js +0 -2
  628. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dockerfile.c5391872.chunk.js.map +0 -1
  629. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dos.3719eb88.chunk.js +0 -2
  630. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dos.3719eb88.chunk.js.map +0 -1
  631. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dsconfig.02aa9b02.chunk.js +0 -2
  632. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dsconfig.02aa9b02.chunk.js.map +0 -1
  633. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dts.aa5834ce.chunk.js +0 -2
  634. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dts.aa5834ce.chunk.js.map +0 -1
  635. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dust.0ea5f8e4.chunk.js +0 -2
  636. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_dust.0ea5f8e4.chunk.js.map +0 -1
  637. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ebnf.2c2f2aa3.chunk.js +0 -2
  638. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ebnf.2c2f2aa3.chunk.js.map +0 -1
  639. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_elixir.6c615dae.chunk.js +0 -2
  640. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_elixir.6c615dae.chunk.js.map +0 -1
  641. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_elm.d76d9c6a.chunk.js +0 -2
  642. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_elm.d76d9c6a.chunk.js.map +0 -1
  643. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_erb.3d58405d.chunk.js +0 -2
  644. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_erb.3d58405d.chunk.js.map +0 -1
  645. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_erlang.23a3e889.chunk.js +0 -2
  646. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_erlang.23a3e889.chunk.js.map +0 -1
  647. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_erlangRepl.b7135450.chunk.js +0 -2
  648. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_erlangRepl.b7135450.chunk.js.map +0 -1
  649. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_excel.4038134c.chunk.js +0 -2
  650. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_excel.4038134c.chunk.js.map +0 -1
  651. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_fix.094e1e53.chunk.js +0 -2
  652. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_fix.094e1e53.chunk.js.map +0 -1
  653. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_flix.10ca5978.chunk.js +0 -2
  654. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_flix.10ca5978.chunk.js.map +0 -1
  655. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_fortran.5d324762.chunk.js +0 -2
  656. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_fortran.5d324762.chunk.js.map +0 -1
  657. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_fsharp.9b01540a.chunk.js +0 -2
  658. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_fsharp.9b01540a.chunk.js.map +0 -1
  659. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gams.2be7938f.chunk.js +0 -2
  660. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gams.2be7938f.chunk.js.map +0 -1
  661. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gauss.9e23cf8a.chunk.js +0 -2
  662. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gauss.9e23cf8a.chunk.js.map +0 -1
  663. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gcode.61385947.chunk.js +0 -2
  664. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gcode.61385947.chunk.js.map +0 -1
  665. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gherkin.4975ce96.chunk.js +0 -2
  666. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gherkin.4975ce96.chunk.js.map +0 -1
  667. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_glsl.a0c0b63b.chunk.js +0 -2
  668. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_glsl.a0c0b63b.chunk.js.map +0 -1
  669. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gml.ea745831.chunk.js +0 -2
  670. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gml.ea745831.chunk.js.map +0 -1
  671. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_go.7ae7638d.chunk.js +0 -2
  672. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_go.7ae7638d.chunk.js.map +0 -1
  673. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_golo.772be59b.chunk.js +0 -2
  674. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_golo.772be59b.chunk.js.map +0 -1
  675. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gradle.c936e1ef.chunk.js +0 -2
  676. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_gradle.c936e1ef.chunk.js.map +0 -1
  677. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_groovy.0225fc76.chunk.js +0 -2
  678. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_groovy.0225fc76.chunk.js.map +0 -1
  679. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_haml.9fe3bfc5.chunk.js +0 -2
  680. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_haml.9fe3bfc5.chunk.js.map +0 -1
  681. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_handlebars.bf22d6a7.chunk.js +0 -2
  682. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_handlebars.bf22d6a7.chunk.js.map +0 -1
  683. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_haskell.a9e34ab1.chunk.js +0 -2
  684. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_haskell.a9e34ab1.chunk.js.map +0 -1
  685. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_haxe.b7b86eb1.chunk.js +0 -2
  686. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_haxe.b7b86eb1.chunk.js.map +0 -1
  687. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_hsp.fdaf68ed.chunk.js +0 -2
  688. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_hsp.fdaf68ed.chunk.js.map +0 -1
  689. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_htmlbars.d1801d48.chunk.js +0 -2
  690. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_htmlbars.d1801d48.chunk.js.map +0 -1
  691. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_http.989f0f7a.chunk.js +0 -2
  692. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_http.989f0f7a.chunk.js.map +0 -1
  693. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_hy.53b6281f.chunk.js +0 -2
  694. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_hy.53b6281f.chunk.js.map +0 -1
  695. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_inform7.fd1e45d6.chunk.js +0 -2
  696. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_inform7.fd1e45d6.chunk.js.map +0 -1
  697. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ini.d50d7548.chunk.js +0 -2
  698. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ini.d50d7548.chunk.js.map +0 -1
  699. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_irpf90.098351d7.chunk.js +0 -2
  700. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_irpf90.098351d7.chunk.js.map +0 -1
  701. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_isbl.e7b7e3e2.chunk.js +0 -2
  702. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_isbl.e7b7e3e2.chunk.js.map +0 -1
  703. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_java.76280439.chunk.js +0 -2
  704. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_java.76280439.chunk.js.map +0 -1
  705. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_javascript.f26037c5.chunk.js +0 -2
  706. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_javascript.f26037c5.chunk.js.map +0 -1
  707. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_jbossCli.a3054510.chunk.js +0 -2
  708. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_jbossCli.a3054510.chunk.js.map +0 -1
  709. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_json.0b331318.chunk.js +0 -2
  710. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_json.0b331318.chunk.js.map +0 -1
  711. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_julia.6e866012.chunk.js +0 -2
  712. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_julia.6e866012.chunk.js.map +0 -1
  713. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_juliaRepl.4e6b450f.chunk.js +0 -2
  714. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_juliaRepl.4e6b450f.chunk.js.map +0 -1
  715. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_kotlin.ed831e93.chunk.js +0 -2
  716. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_kotlin.ed831e93.chunk.js.map +0 -1
  717. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_lasso.dd03d6c9.chunk.js +0 -2
  718. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_lasso.dd03d6c9.chunk.js.map +0 -1
  719. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_latex.376a33c7.chunk.js +0 -2
  720. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_latex.376a33c7.chunk.js.map +0 -1
  721. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ldif.f64a4c1a.chunk.js +0 -2
  722. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ldif.f64a4c1a.chunk.js.map +0 -1
  723. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_leaf.7fe5ae9f.chunk.js +0 -2
  724. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_leaf.7fe5ae9f.chunk.js.map +0 -1
  725. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_less.c7c9b20f.chunk.js +0 -2
  726. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_less.c7c9b20f.chunk.js.map +0 -1
  727. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_lisp.4ca35eb5.chunk.js +0 -2
  728. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_lisp.4ca35eb5.chunk.js.map +0 -1
  729. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_livecodeserver.f6202053.chunk.js +0 -2
  730. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_livecodeserver.f6202053.chunk.js.map +0 -1
  731. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_livescript.ad10ad81.chunk.js +0 -2
  732. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_livescript.ad10ad81.chunk.js.map +0 -1
  733. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_llvm.dfeb835c.chunk.js +0 -2
  734. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_llvm.dfeb835c.chunk.js.map +0 -1
  735. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_lsl.98983a45.chunk.js +0 -2
  736. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_lsl.98983a45.chunk.js.map +0 -1
  737. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_lua.3f6c5937.chunk.js +0 -2
  738. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_lua.3f6c5937.chunk.js.map +0 -1
  739. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_makefile.26a94240.chunk.js +0 -2
  740. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_makefile.26a94240.chunk.js.map +0 -1
  741. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_markdown.7fda17b5.chunk.js +0 -2
  742. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_markdown.7fda17b5.chunk.js.map +0 -1
  743. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mathematica.3709c63c.chunk.js +0 -2
  744. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mathematica.3709c63c.chunk.js.map +0 -1
  745. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_matlab.14688fbd.chunk.js +0 -2
  746. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_matlab.14688fbd.chunk.js.map +0 -1
  747. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_maxima.81aa795f.chunk.js +0 -2
  748. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_maxima.81aa795f.chunk.js.map +0 -1
  749. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mel.15154a79.chunk.js +0 -2
  750. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mel.15154a79.chunk.js.map +0 -1
  751. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mercury.7dff62e6.chunk.js +0 -2
  752. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mercury.7dff62e6.chunk.js.map +0 -1
  753. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mipsasm.a58980c2.chunk.js +0 -2
  754. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mipsasm.a58980c2.chunk.js.map +0 -1
  755. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mizar.372b0863.chunk.js +0 -2
  756. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mizar.372b0863.chunk.js.map +0 -1
  757. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mojolicious.f8890e29.chunk.js +0 -2
  758. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_mojolicious.f8890e29.chunk.js.map +0 -1
  759. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_monkey.f200dd5a.chunk.js +0 -2
  760. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_monkey.f200dd5a.chunk.js.map +0 -1
  761. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_moonscript.0a887ad7.chunk.js +0 -2
  762. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_moonscript.0a887ad7.chunk.js.map +0 -1
  763. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_n1ql.7546d8a8.chunk.js +0 -2
  764. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_n1ql.7546d8a8.chunk.js.map +0 -1
  765. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nginx.54a04b57.chunk.js +0 -2
  766. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nginx.54a04b57.chunk.js.map +0 -1
  767. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nim.5268767b.chunk.js +0 -2
  768. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nim.5268767b.chunk.js.map +0 -1
  769. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nix.cea6e933.chunk.js +0 -2
  770. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nix.cea6e933.chunk.js.map +0 -1
  771. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nodeRepl.0226aff6.chunk.js +0 -2
  772. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nodeRepl.0226aff6.chunk.js.map +0 -1
  773. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nsis.335a4367.chunk.js +0 -2
  774. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_nsis.335a4367.chunk.js.map +0 -1
  775. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_objectivec.1df8f7a8.chunk.js +0 -2
  776. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_objectivec.1df8f7a8.chunk.js.map +0 -1
  777. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ocaml.18424877.chunk.js +0 -2
  778. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ocaml.18424877.chunk.js.map +0 -1
  779. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_oneC.5fff5251.chunk.js +0 -2
  780. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_oneC.5fff5251.chunk.js.map +0 -1
  781. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_openscad.4fdc4694.chunk.js +0 -2
  782. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_openscad.4fdc4694.chunk.js.map +0 -1
  783. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_oxygene.1f8278af.chunk.js +0 -2
  784. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_oxygene.1f8278af.chunk.js.map +0 -1
  785. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_parser3.b546962d.chunk.js +0 -2
  786. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_parser3.b546962d.chunk.js.map +0 -1
  787. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_perl.2dbbe598.chunk.js +0 -2
  788. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_perl.2dbbe598.chunk.js.map +0 -1
  789. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_pf.ad96a59e.chunk.js +0 -2
  790. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_pf.ad96a59e.chunk.js.map +0 -1
  791. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_pgsql.fbe2b4dc.chunk.js +0 -2
  792. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_pgsql.fbe2b4dc.chunk.js.map +0 -1
  793. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_php.0e74e4da.chunk.js +0 -2
  794. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_php.0e74e4da.chunk.js.map +0 -1
  795. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_phpTemplate.14a40d68.chunk.js +0 -2
  796. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_phpTemplate.14a40d68.chunk.js.map +0 -1
  797. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_plaintext.a92f0bc6.chunk.js +0 -2
  798. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_plaintext.a92f0bc6.chunk.js.map +0 -1
  799. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_pony.1ecfd6cc.chunk.js +0 -2
  800. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_pony.1ecfd6cc.chunk.js.map +0 -1
  801. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_powershell.ffb08d81.chunk.js +0 -2
  802. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_powershell.ffb08d81.chunk.js.map +0 -1
  803. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_processing.d849b421.chunk.js +0 -2
  804. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_processing.d849b421.chunk.js.map +0 -1
  805. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_profile.7b1beaa3.chunk.js +0 -2
  806. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_profile.7b1beaa3.chunk.js.map +0 -1
  807. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_prolog.0430c793.chunk.js +0 -2
  808. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_prolog.0430c793.chunk.js.map +0 -1
  809. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_properties.b76b184d.chunk.js +0 -2
  810. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_properties.b76b184d.chunk.js.map +0 -1
  811. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_protobuf.4b3983b2.chunk.js +0 -2
  812. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_protobuf.4b3983b2.chunk.js.map +0 -1
  813. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_puppet.a6e8526c.chunk.js +0 -2
  814. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_puppet.a6e8526c.chunk.js.map +0 -1
  815. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_purebasic.ee001b77.chunk.js +0 -2
  816. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_purebasic.ee001b77.chunk.js.map +0 -1
  817. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_python.aea72199.chunk.js +0 -2
  818. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_python.aea72199.chunk.js.map +0 -1
  819. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_pythonRepl.12dcde8e.chunk.js +0 -2
  820. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_pythonRepl.12dcde8e.chunk.js.map +0 -1
  821. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_q.ebfb1165.chunk.js +0 -2
  822. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_q.ebfb1165.chunk.js.map +0 -1
  823. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_qml.d164145e.chunk.js +0 -2
  824. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_qml.d164145e.chunk.js.map +0 -1
  825. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_r.b65b635e.chunk.js +0 -2
  826. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_r.b65b635e.chunk.js.map +0 -1
  827. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_reasonml.04b21c23.chunk.js +0 -2
  828. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_reasonml.04b21c23.chunk.js.map +0 -1
  829. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_rib.a862cb87.chunk.js +0 -2
  830. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_rib.a862cb87.chunk.js.map +0 -1
  831. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_roboconf.f4ed1e36.chunk.js +0 -2
  832. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_roboconf.f4ed1e36.chunk.js.map +0 -1
  833. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_routeros.25c613b9.chunk.js +0 -2
  834. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_routeros.25c613b9.chunk.js.map +0 -1
  835. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_rsl.bdd516e7.chunk.js +0 -2
  836. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_rsl.bdd516e7.chunk.js.map +0 -1
  837. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ruby.9c24a54b.chunk.js +0 -2
  838. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ruby.9c24a54b.chunk.js.map +0 -1
  839. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ruleslanguage.1f12103d.chunk.js +0 -2
  840. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_ruleslanguage.1f12103d.chunk.js.map +0 -1
  841. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_rust.36fa84d5.chunk.js +0 -2
  842. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_rust.36fa84d5.chunk.js.map +0 -1
  843. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sas.0fb2b090.chunk.js +0 -2
  844. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sas.0fb2b090.chunk.js.map +0 -1
  845. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_scala.f1e91dc8.chunk.js +0 -2
  846. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_scala.f1e91dc8.chunk.js.map +0 -1
  847. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_scheme.61209260.chunk.js +0 -2
  848. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_scheme.61209260.chunk.js.map +0 -1
  849. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_scilab.8456e602.chunk.js +0 -2
  850. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_scilab.8456e602.chunk.js.map +0 -1
  851. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_scss.7fe28a7c.chunk.js +0 -2
  852. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_scss.7fe28a7c.chunk.js.map +0 -1
  853. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_shell.02ed5281.chunk.js +0 -2
  854. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_shell.02ed5281.chunk.js.map +0 -1
  855. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_smali.ac2a56e0.chunk.js +0 -2
  856. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_smali.ac2a56e0.chunk.js.map +0 -1
  857. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_smalltalk.0b3337c5.chunk.js +0 -2
  858. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_smalltalk.0b3337c5.chunk.js.map +0 -1
  859. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sml.392ebc86.chunk.js +0 -2
  860. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sml.392ebc86.chunk.js.map +0 -1
  861. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sqf.f314350f.chunk.js +0 -2
  862. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sqf.f314350f.chunk.js.map +0 -1
  863. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sql.29cd33d8.chunk.js +0 -2
  864. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sql.29cd33d8.chunk.js.map +0 -1
  865. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sqlMore.cf69ab0f.chunk.js +0 -2
  866. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_sqlMore.cf69ab0f.chunk.js.map +0 -1
  867. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_stan.3caa2fde.chunk.js +0 -2
  868. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_stan.3caa2fde.chunk.js.map +0 -1
  869. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_stata.67ee27ff.chunk.js +0 -2
  870. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_stata.67ee27ff.chunk.js.map +0 -1
  871. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_step21.57a3be37.chunk.js +0 -2
  872. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_step21.57a3be37.chunk.js.map +0 -1
  873. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_stylus.29d5eba1.chunk.js +0 -2
  874. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_stylus.29d5eba1.chunk.js.map +0 -1
  875. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_subunit.53c1150c.chunk.js +0 -2
  876. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_subunit.53c1150c.chunk.js.map +0 -1
  877. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_swift.6b1f5aee.chunk.js +0 -2
  878. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_swift.6b1f5aee.chunk.js.map +0 -1
  879. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_taggerscript.4e318a46.chunk.js +0 -2
  880. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_taggerscript.4e318a46.chunk.js.map +0 -1
  881. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_tap.aad22555.chunk.js +0 -2
  882. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_tap.aad22555.chunk.js.map +0 -1
  883. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_tcl.6c2ca652.chunk.js +0 -2
  884. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_tcl.6c2ca652.chunk.js.map +0 -1
  885. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_thrift.0a78f030.chunk.js +0 -2
  886. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_thrift.0a78f030.chunk.js.map +0 -1
  887. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_tp.ced050b4.chunk.js +0 -2
  888. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_tp.ced050b4.chunk.js.map +0 -1
  889. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_twig.3cf1f762.chunk.js +0 -2
  890. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_twig.3cf1f762.chunk.js.map +0 -1
  891. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_typescript.8271e09e.chunk.js +0 -2
  892. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_typescript.8271e09e.chunk.js.map +0 -1
  893. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vala.9ec5fefa.chunk.js +0 -2
  894. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vala.9ec5fefa.chunk.js.map +0 -1
  895. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vbnet.500e353c.chunk.js +0 -2
  896. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vbnet.500e353c.chunk.js.map +0 -1
  897. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vbscript.1f751b10.chunk.js +0 -2
  898. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vbscript.1f751b10.chunk.js.map +0 -1
  899. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vbscriptHtml.4db9996e.chunk.js +0 -2
  900. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vbscriptHtml.4db9996e.chunk.js.map +0 -1
  901. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_verilog.74aa0d6e.chunk.js +0 -2
  902. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_verilog.74aa0d6e.chunk.js.map +0 -1
  903. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vhdl.e4237fb3.chunk.js +0 -2
  904. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vhdl.e4237fb3.chunk.js.map +0 -1
  905. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vim.58fb019d.chunk.js +0 -2
  906. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_vim.58fb019d.chunk.js.map +0 -1
  907. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_x86asm.8dfba317.chunk.js +0 -2
  908. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_x86asm.8dfba317.chunk.js.map +0 -1
  909. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_xl.fb466219.chunk.js +0 -2
  910. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_xl.fb466219.chunk.js.map +0 -1
  911. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_xml.56397e06.chunk.js +0 -2
  912. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_xml.56397e06.chunk.js.map +0 -1
  913. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_xquery.9b175b45.chunk.js +0 -2
  914. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_xquery.9b175b45.chunk.js.map +0 -1
  915. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_yaml.1719efae.chunk.js +0 -2
  916. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_yaml.1719efae.chunk.js.map +0 -1
  917. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_zephir.0b762be7.chunk.js +0 -2
  918. package/dist/embedded-app/static/react-syntax-highlighter_languages_highlight_zephir.0b762be7.chunk.js.map +0 -1
  919. package/dist/embedded-app/static/runtime.9ead869c.js +0 -2
  920. package/dist/embedded-app/static/runtime.9ead869c.js.map +0 -1
  921. package/dist/embedded-app/static/vendor.9ead869c.js +0 -2
  922. package/dist/embedded-app/static/vendor.9ead869c.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"static/main.9ead869c.js","sources":["webpack://techdocs-cli-embedded-app/../catalog-client/src/types/api.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/entity/constants.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/entity/ref.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/kinds/relations.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/location/annotation.ts","webpack://techdocs-cli-embedded-app/../catalog-model/src/location/helpers.ts","webpack://techdocs-cli-embedded-app/../core-components/src/components/CodeSnippet/CodeSnippet.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/CopyTextButton/CopyTextButton.tsx","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/ErrorPanel/ErrorPanel.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/FavoriteToggle/FavoriteToggle.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Link/Link.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/LinkButton/LinkButton.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/MarkdownContent/MarkdownContent.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Progress/Progress.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/SupportButton/SupportButton.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/../core-components/src/components/WarningPanel/WarningPanel.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/hooks/useSupportConfig.ts","webpack://techdocs-cli-embedded-app/../core-components/src/icons/icons.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Content/Content.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/ContentHeader/ContentHeader.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/ErrorPage/MicDrop.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/ErrorPage/StackDetails.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/ErrorPage/ErrorPage.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Breadcrumbs/Breadcrumbs.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Header/Header.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Page/Page.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Page/PageWithHeader.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Sidebar/localStorage.ts","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Sidebar/Page.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Sidebar/SidebarPinStateContext.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Sidebar/config.ts","webpack://techdocs-cli-embedded-app/../core-components/src/translation.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/analytics/AnalyticsContext.tsx","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/analytics/Tracker.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/analytics/useAnalytics.tsx","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/definitions/AlertApi.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/definitions/AnalyticsApi.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/definitions/ConfigApi.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/definitions/DiscoveryApi.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/definitions/ErrorApi.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/definitions/FeatureFlagsApi.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/definitions/FetchApi.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/definitions/IdentityApi.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/definitions/TranslationApi.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/system/ApiRef.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/system/helpers.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/system/useApi.tsx","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/app/useApp.tsx","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/extensions/componentData.tsx","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/extensions/PluginErrorBoundary.tsx","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/extensions/extensions.tsx","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/extensions/useElementFilter.tsx","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/plugin/Plugin.tsx","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/routing/RouteRef.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/routing/types.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/routing/useRouteRef.tsx","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/translation/TranslationRef.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/translation/TranslationResource.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/translation/useTranslationRef.ts","webpack://techdocs-cli-embedded-app/../errors/src/serialization/response.ts","webpack://techdocs-cli-embedded-app/../errors/src/errors/ResponseError.ts","webpack://techdocs-cli-embedded-app/../errors/src/errors/assertion.ts","webpack://techdocs-cli-embedded-app/../errors/src/errors/CustomErrorBase.ts","webpack://techdocs-cli-embedded-app/../errors/src/errors/common.ts","webpack://techdocs-cli-embedded-app/../errors/src/serialization/error.ts","webpack://techdocs-cli-embedded-app/../integration/src/awsS3/config.ts","webpack://techdocs-cli-embedded-app/../integration/src/awsS3/AwsS3Integration.ts","webpack://techdocs-cli-embedded-app/../integration/src/awsCodeCommit/config.ts","webpack://techdocs-cli-embedded-app/../integration/src/awsCodeCommit/AwsCodeCommitIntegration.ts","webpack://techdocs-cli-embedded-app/../integration/src/azure/AzureUrl.ts","webpack://techdocs-cli-embedded-app/../integration/src/azure/config.ts","webpack://techdocs-cli-embedded-app/../integration/src/azure/AzureIntegration.ts","webpack://techdocs-cli-embedded-app/../integration/src/bitbucketCloud/config.ts","webpack://techdocs-cli-embedded-app/../integration/src/bitbucketCloud/BitbucketCloudIntegration.ts","webpack://techdocs-cli-embedded-app/../integration/src/bitbucket/config.ts","webpack://techdocs-cli-embedded-app/../integration/src/bitbucket/BitbucketIntegration.ts","webpack://techdocs-cli-embedded-app/../integration/src/bitbucketServer/config.ts","webpack://techdocs-cli-embedded-app/../integration/src/bitbucketServer/BitbucketServerIntegration.ts","webpack://techdocs-cli-embedded-app/../integration/src/gerrit/config.ts","webpack://techdocs-cli-embedded-app/../integration/src/gerrit/core.ts","webpack://techdocs-cli-embedded-app/../integration/src/gerrit/GerritIntegration.ts","webpack://techdocs-cli-embedded-app/../integration/src/gitlab/config.ts","webpack://techdocs-cli-embedded-app/../integration/src/gitlab/GitLabIntegration.ts","webpack://techdocs-cli-embedded-app/../integration/src/gitea/GiteaIntegration.ts","webpack://techdocs-cli-embedded-app/../integration/src/gitea/config.ts","webpack://techdocs-cli-embedded-app/../integration/src/gitea/core.ts","webpack://techdocs-cli-embedded-app/../integration/src/harness/HarnessIntegration.ts","webpack://techdocs-cli-embedded-app/../integration/src/harness/config.ts","webpack://techdocs-cli-embedded-app/../integration/src/harness/core.ts","webpack://techdocs-cli-embedded-app/../integration/src/azureBlobStorage/config.ts","webpack://techdocs-cli-embedded-app/../integration/src/azureBlobStorage/AzureBlobStorageIntegration.ts","webpack://techdocs-cli-embedded-app/../integration/src/ScmIntegrations.ts","webpack://techdocs-cli-embedded-app/../integration-react/src/api/ScmIntegrationsApi.ts","webpack://techdocs-cli-embedded-app/../integration/src/github/config.ts","webpack://techdocs-cli-embedded-app/../integration/src/github/GithubIntegration.ts","webpack://techdocs-cli-embedded-app/../integration/src/helpers.ts","webpack://techdocs-cli-embedded-app/../app-defaults/src/createApp.tsx","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/definitions/auth.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/system/ApiFactoryRegistry.ts","webpack://techdocs-cli-embedded-app/../app-defaults/src/defaults/components.tsx","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/DiscoveryApi/UrlPatternDiscovery.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/DiscoveryApi/FrontendHostDiscovery.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/lib/subjects.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/AlertApi/AlertApiForwarder.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/AnalyticsApi/NoOpAnalyticsApi.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/ErrorApi/ErrorAlerter.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/ErrorApi/ErrorApiForwarder.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/ErrorApi/UnhandledErrorForwarder.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/StorageApi/WebStorage.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/FetchApi/IdentityAuthInjectorFetchMiddleware.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/FetchApi/PluginProtocolResolverFetchMiddleware.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/FetchApi/FetchMiddlewares.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/OAuthRequestApi/OAuthPendingRequests.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/OAuthRequestApi/OAuthRequestManager.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/lib/AuthConnector/DefaultAuthConnector.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/lib/loginPopup.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/lib/AuthSessionManager/common.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/lib/AuthSessionManager/SessionStateTracker.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/lib/AuthSessionManager/RefreshingAuthSessionManager.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/auth/oauth2/OAuth2.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/auth/google/GoogleAuth.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/auth/github/GithubAuth.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/auth/okta/OktaAuth.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/auth/gitlab/GitlabAuth.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/auth/onelogin/OneLoginAuth.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/auth/bitbucket/BitbucketAuth.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/auth/atlassian/AtlassianAuth.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/auth/vmwareCloud/VMwareCloudAuth.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/definitions/StorageApi.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/definitions/OAuthRequestApi.ts","webpack://techdocs-cli-embedded-app/../../plugins/permission-common/src/PermissionClient.ts","webpack://techdocs-cli-embedded-app/../../plugins/permission-react/src/apis/IdentityPermissionApi.ts","webpack://techdocs-cli-embedded-app/../app-defaults/src/defaults/apis.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/FetchApi/createFetchApi.ts","webpack://techdocs-cli-embedded-app/../app-defaults/src/defaults/icons.tsx","webpack://techdocs-cli-embedded-app/../theme/src/unified/UnifiedThemeProvider.tsx","webpack://techdocs-cli-embedded-app/../theme/src/base/pageTheme.ts","webpack://techdocs-cli-embedded-app/../theme/src/base/createBaseThemeOptions.ts","webpack://techdocs-cli-embedded-app/../theme/src/v5/defaultComponentThemes.ts","webpack://techdocs-cli-embedded-app/../theme/src/unified/overrides.ts","webpack://techdocs-cli-embedded-app/../theme/src/unified/UnifiedTheme.tsx","webpack://techdocs-cli-embedded-app/../theme/src/unified/themes.ts","webpack://techdocs-cli-embedded-app/../theme/src/base/palettes.ts","webpack://techdocs-cli-embedded-app/../app-defaults/src/defaults/themes.tsx","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/system/ApiAggregator.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/system/ApiProvider.tsx","webpack://techdocs-cli-embedded-app/../config/src/reader.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/AppThemeApi/AppThemeSelector.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/definitions/AppThemeApi.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/apis/definitions/AppLanguageApi.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/system/ApiResolver.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/extensions/traversal.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/plugins/collectors.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/routing/FeatureFlagged.tsx","webpack://techdocs-cli-embedded-app/../core-app-api/src/routing/collectors.tsx","webpack://techdocs-cli-embedded-app/../core-app-api/src/routing/types.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/routing/helpers.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/routing/RouteResolver.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/routing/RoutingProvider.tsx","webpack://techdocs-cli-embedded-app/../core-app-api/src/app/AppContext.tsx","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/IdentityApi/startCookieAuthRefresh.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/app/AppThemeProvider.tsx","webpack://techdocs-cli-embedded-app/../core-app-api/src/app/defaultConfigLoader.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/system/ApiRegistry.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/app/isReactRouterBeta.tsx","webpack://techdocs-cli-embedded-app/../core-app-api/src/app/InternalAppContext.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/routing/RouteTracker.tsx","webpack://techdocs-cli-embedded-app/../core-app-api/src/app/AppRouter.tsx","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/AppLanguageApi/AppLanguageSelector.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/app/overrideBaseUrlConfigs.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/app/AppManager.tsx","webpack://techdocs-cli-embedded-app/../core-app-api/src/app/resolveRouteBindings.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/routing/validation.ts","webpack://techdocs-cli-embedded-app/../core-app-api/src/app/isProtectedApp.tsx","webpack://techdocs-cli-embedded-app/../core-app-api/src/routing/FlatRoutes.tsx","webpack://techdocs-cli-embedded-app/../catalog-client/src/schema/openapi/generated/pluginId.ts","webpack://techdocs-cli-embedded-app/../catalog-client/src/schema/openapi/generated/apis/Api.client.ts","webpack://techdocs-cli-embedded-app/../catalog-client/src/CatalogClient.ts","webpack://techdocs-cli-embedded-app/../catalog-client/src/utils.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog/src/apis/StarredEntitiesApi/migration.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog/src/apis/StarredEntitiesApi/DefaultStarredEntitiesApi.ts","webpack://techdocs-cli-embedded-app/../types/src/time.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog/src/apis/EntityPresentationApi/defaults.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog/src/apis/EntityPresentationApi/DefaultEntityPresentationApi.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog/src/plugin.ts","webpack://techdocs-cli-embedded-app/./src/apis.ts","webpack://techdocs-cli-embedded-app/./src/config.ts","webpack://techdocs-cli-embedded-app/./src/components/Root/LogoFull.tsx","webpack://techdocs-cli-embedded-app/./src/components/Root/LogoIcon.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Sidebar/SidebarOpenStateContext.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Sidebar/MobileSidebarContext.ts","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Sidebar/SidebarGroup.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Sidebar/MobileSidebar.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Sidebar/Bar.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Sidebar/SidebarSubmenu.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Sidebar/utils.ts","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Sidebar/Items.tsx","webpack://techdocs-cli-embedded-app/./src/components/Root/Root.tsx","webpack://techdocs-cli-embedded-app/./src/components/TechDocsPage/TechDocsPage.tsx","webpack://techdocs-cli-embedded-app/./src/App.tsx","webpack://techdocs-cli-embedded-app/../core-app-api/src/app/createSpecializedApp.tsx","webpack://techdocs-cli-embedded-app/./src/index.tsx","webpack://techdocs-cli-embedded-app/../version-bridge/src/lib/VersionedContext.ts","webpack://techdocs-cli-embedded-app/../version-bridge/src/lib/VersionedValue.ts","webpack://techdocs-cli-embedded-app/../version-bridge/src/lib/globalObject.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/api.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/apis/EntityPresentationApi/EntityPresentationApi.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/apis/EntityPresentationApi/defaultEntityPresentation.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/apis/EntityPresentationApi/useEntityPresentation.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/apis/EntityPresentationApi/useUpdatingObservable.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/apis/StarredEntitiesApi/StarredEntitiesApi.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/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/EntityDisplayName/EntityDisplayName.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityRefLink/EntityRefLinks.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityRefLink/humanize.ts","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/routes.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/translation.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/../core-plugin-api/src/routing/ExternalRouteRef.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog/src/routes.ts","webpack://techdocs-cli-embedded-app/../../plugins/permission-common/src/permissions/util.ts","webpack://techdocs-cli-embedded-app/../../plugins/permission-common/src/types/api.ts","webpack://techdocs-cli-embedded-app/../../plugins/permission-react/src/apis/PermissionApi.ts","webpack://techdocs-cli-embedded-app/../../plugins/search-react/src/components/HighlightedSearchResultText/HighlightedSearchResultText.tsx","webpack://techdocs-cli-embedded-app/../../plugins/search-react/src/extensions.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs-common/src/constants.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs-react/src/addons.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs-react/src/api.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs-react/src/context.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs-react/src/helpers.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs-react/src/types.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/helpers.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/TechDocsPicker.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/DefaultTechDocsHome.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/DocsTable.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/TechDocsPageWrapper.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/client.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/plugin.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/renderReactElement.ts","webpack://techdocs-cli-embedded-app/../../plugins/search-react/src/components/SearchAutocomplete/SearchAutocomplete.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsReaderProvider.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs-react/src/component.tsx","webpack://techdocs-cli-embedded-app/../../plugins/search-react/src/api.ts","webpack://techdocs-cli-embedded-app/../../plugins/search-react/src/context/SearchContext.tsx","webpack://techdocs-cli-embedded-app/../../plugins/search-react/src/translation.ts","webpack://techdocs-cli-embedded-app/../../plugins/search-react/src/components/SearchBar/SearchBar.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/search/components/TechDocsSearch.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/LogViewer/LogViewer.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsBuildLogs.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsNotFound.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/useReaderState.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsStateIndicator.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/html/hooks/links.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/styles/rules/typeset.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/styles/rules/palette.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/styles/rules/rules.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/styles/rules/variables.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/styles/rules/reset.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/styles/rules/layout.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/styles/rules/animations.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/styles/rules/extensions.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/transformer.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/addBaseUrl.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/rewriteDocLinks.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsRedirectNotification/TechDocsRedirectNotification.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/copyToClipboard.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/onCssReady.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContentAddons.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsReaderPageContent/useNavigateUrl.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/html/transformer.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/html/hooks/iframes.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/styles/transformer.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/addSidebarToggle.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/removeMkdocsHeader.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/simplifyMkdocsFooter.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/addGitFeedbackLink.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/handleMetaRedirects.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/scrollIntoNavigation.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/addLinkClickListener.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/transformers/addNavLinkKeyboardToggle.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs-react/src/hooks.ts","webpack://techdocs-cli-embedded-app/../core-components/src/layout/HeaderLabel/HeaderLabel.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/routes.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx","webpack://techdocs-cli-embedded-app/../cli/config/webpack-public-path.js"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { CompoundEntityRef, Entity } from '@backstage/catalog-model';\nimport { SerializedError } from '@backstage/errors';\nimport type {\n AnalyzeLocationRequest,\n AnalyzeLocationResponse,\n} from '@backstage/plugin-catalog-common';\n\n/**\n * This symbol can be used in place of a value when passed to filters in e.g.\n * {@link CatalogClient.getEntities}, to signify that you want to filter on the\n * presence of that key no matter what its value is.\n *\n * @public\n */\nexport const CATALOG_FILTER_EXISTS = Symbol.for(\n // Random UUID to ensure no collisions\n 'CATALOG_FILTER_EXISTS_0e15b590c0b343a2bae3e787e84c2111',\n);\n\n/**\n * A key-value based filter expression for entities.\n *\n * @remarks\n *\n * Each key of a record is a dot-separated path into the entity structure, e.g.\n * `metadata.name`.\n *\n * The values are literal values to match against. As a value you can also pass\n * in the symbol `CATALOG_FILTER_EXISTS` (exported from this package), which\n * means that you assert on the existence of that key, no matter what its value\n * is.\n *\n * All matching of keys and values is case insensitive.\n *\n * If multiple filter sets are given as an array, then there is effectively an\n * OR between each filter set.\n *\n * Within one filter set, there is effectively an AND between the various keys.\n *\n * Within one key, if there are more than one value, then there is effectively\n * an OR between them.\n *\n * Example: For an input of\n *\n * ```\n * [\n * { kind: ['API', 'Component'] },\n * { 'metadata.name': 'a', 'metadata.namespace': 'b' }\n * ]\n * ```\n *\n * This effectively means\n *\n * ```\n * (kind = EITHER 'API' OR 'Component')\n * OR\n * (metadata.name = 'a' AND metadata.namespace = 'b' )\n * ```\n *\n * @public\n */\nexport type EntityFilterQuery =\n | Record<string, string | symbol | (string | symbol)[]>[]\n | Record<string, string | symbol | (string | symbol)[]>;\n\n/**\n * A set of dot-separated paths into an entity's keys, showing what parts of an\n * entity to include in a response, and excluding all others.\n *\n * @remarks\n *\n * Example: For an input of `['kind', 'metadata.annotations']`, then response\n * objects will be shaped like\n *\n * ```\n * {\n * \"kind\": \"Component\",\n * \"metadata\": {\n * \"annotations\": {\n * \"foo\": \"bar\"\n * }\n * }\n * }\n * ```\n * @public\n */\nexport type EntityFieldsQuery = string[];\n\n/**\n * Dot-separated field based ordering directives, controlling the sort order of\n * the output entities.\n *\n * @remarks\n *\n * Each field is a dot-separated path into an entity's keys. The order is either\n * ascending (`asc`, lexicographical order) or descending (`desc`, reverse\n * lexicographical order). The ordering is case insensitive.\n *\n * If more than one order directive is given, later directives have lower\n * precedence (they are applied only when directives of higher precedence have\n * equal values).\n *\n * Example:\n *\n * ```\n * [\n * { field: 'kind', order: 'asc' },\n * { field: 'metadata.name', order: 'desc' },\n * ]\n * ```\n *\n * This will order the output first by kind ascending, and then within each kind\n * (if there's more than one of a given kind) by their name descending.\n *\n * When given a field that does NOT exist on all entities in the result set,\n * those entities that do not have the field will always be sorted last in that\n * particular order step, no matter what the desired order was.\n *\n * @public\n */\nexport type EntityOrderQuery =\n | {\n field: string;\n order: 'asc' | 'desc';\n }\n | Array<{\n field: string;\n order: 'asc' | 'desc';\n }>;\n\n/**\n * The request type for {@link CatalogClient.getEntities}.\n *\n * @public\n */\nexport interface GetEntitiesRequest {\n /**\n * If given, return only entities that match the given filter.\n */\n filter?: EntityFilterQuery;\n /**\n * If given, return only the parts of each entity that match the field\n * declarations.\n */\n fields?: EntityFieldsQuery;\n /**\n *If given, order the result set by those directives.\n */\n order?: EntityOrderQuery;\n /**\n * If given, skips over the first N items in the result set.\n */\n offset?: number;\n /**\n * If given, returns at most N items from the result set.\n */\n limit?: number;\n /**\n * If given, skips over all items before that cursor as returned by a previous\n * request.\n */\n after?: string;\n}\n\n/**\n * The response type for {@link CatalogClient.getEntities}.\n *\n * @public\n */\nexport interface GetEntitiesResponse {\n items: Entity[];\n}\n\n/**\n * The request type for {@link CatalogClient.getEntitiesByRefs}.\n *\n * @public\n */\nexport interface GetEntitiesByRefsRequest {\n /**\n * The list of entity refs to fetch.\n *\n * @remarks\n *\n * The returned list of entities will be in the same order as the refs, and\n * null will be returned in those positions that were not found.\n */\n entityRefs: string[];\n /**\n * If given, return only the parts of each entity that match the field\n * declarations.\n */\n fields?: EntityFieldsQuery | undefined;\n /**\n * If given, return only entities that match the given filter.\n */\n filter?: EntityFilterQuery;\n}\n\n/**\n * The response type for {@link CatalogClient.getEntitiesByRefs}.\n *\n * @public\n */\nexport interface GetEntitiesByRefsResponse {\n /**\n * The returned list of entities.\n *\n * @remarks\n *\n * The list will be in the same order as the refs given in the request, and\n * null will be returned in those positions that were not found.\n */\n items: Array<Entity | undefined>;\n}\n\n/**\n * The request type for {@link CatalogClient.getEntityAncestors}.\n *\n * @public\n */\nexport interface GetEntityAncestorsRequest {\n entityRef: string;\n}\n\n/**\n * The response type for {@link CatalogClient.getEntityAncestors}.\n *\n * @public\n */\nexport interface GetEntityAncestorsResponse {\n rootEntityRef: string;\n items: Array<{\n entity: Entity;\n parentEntityRefs: string[];\n }>;\n}\n\n/**\n * The request type for {@link CatalogClient.getEntityFacets}.\n *\n * @public\n */\nexport interface GetEntityFacetsRequest {\n /**\n * If given, return only entities that match the given patterns.\n *\n * @remarks\n *\n * If multiple filter sets are given as an array, then there is effectively an\n * OR between each filter set.\n *\n * Within one filter set, there is effectively an AND between the various\n * keys.\n *\n * Within one key, if there are more than one value, then there is effectively\n * an OR between them.\n *\n * Example: For an input of\n *\n * ```\n * [\n * { kind: ['API', 'Component'] },\n * { 'metadata.name': 'a', 'metadata.namespace': 'b' }\n * ]\n * ```\n *\n * This effectively means\n *\n * ```\n * (kind = EITHER 'API' OR 'Component')\n * OR\n * (metadata.name = 'a' AND metadata.namespace = 'b' )\n * ```\n *\n * Each key is a dot separated path in each object.\n *\n * As a value you can also pass in the symbol `CATALOG_FILTER_EXISTS`\n * (exported from this package), which means that you assert on the existence\n * of that key, no matter what its value is.\n */\n filter?: EntityFilterQuery;\n /**\n * Dot separated paths for the facets to extract from each entity.\n *\n * @remarks\n *\n * Example: For an input of `['kind', 'metadata.annotations.backstage.io/orphan']`, then the\n * response will be shaped like\n *\n * ```\n * {\n * \"facets\": {\n * \"kind\": [\n * { \"key\": \"Component\", \"count\": 22 },\n * { \"key\": \"API\", \"count\": 13 }\n * ],\n * \"metadata.annotations.backstage.io/orphan\": [\n * { \"key\": \"true\", \"count\": 2 }\n * ]\n * }\n * }\n * ```\n */\n facets: string[];\n}\n\n/**\n * The response type for {@link CatalogClient.getEntityFacets}.\n *\n * @public\n */\nexport interface GetEntityFacetsResponse {\n /**\n * The computed facets, one entry per facet in the request.\n */\n facets: Record<string, Array<{ value: string; count: number }>>;\n}\n\n/**\n * Options you can pass into a catalog request for additional information.\n *\n * @public\n */\nexport interface CatalogRequestOptions {\n token?: string;\n}\n\n/**\n * Entity location for a specific entity.\n *\n * @public\n */\nexport type Location = {\n id: string;\n type: string;\n target: string;\n};\n\n/**\n * The response type for {@link CatalogClient.getLocations}\n *\n * @public\n */\nexport interface GetLocationsResponse {\n items: Location[];\n}\n\n/**\n * The request type for {@link CatalogClient.addLocation}.\n *\n * @public\n */\nexport type AddLocationRequest = {\n type?: string;\n target: string;\n /**\n * If set to true, the location will not be added, but the response will\n * contain the entities that match the given location.\n */\n dryRun?: boolean;\n};\n\n/**\n * The response type for {@link CatalogClient.addLocation}.\n *\n * @public\n */\nexport type AddLocationResponse = {\n location: Location;\n /**\n * The entities matching this location. Will only be filled in dryRun mode\n */\n entities: Entity[];\n /**\n * True, if the location exists. Will only be filled in dryRun mode\n */\n exists?: boolean;\n};\n\n/**\n * The response type for {@link CatalogClient.validateEntity}\n *\n * @public\n */\nexport type ValidateEntityResponse =\n | { valid: true }\n | { valid: false; errors: SerializedError[] };\n\n/**\n * The request type for {@link CatalogClient.queryEntities}.\n *\n * @public\n */\nexport type QueryEntitiesRequest =\n | QueryEntitiesInitialRequest\n | QueryEntitiesCursorRequest;\n\n/**\n * A request type for {@link CatalogClient.queryEntities}.\n * The method takes this type in an initial pagination request,\n * when requesting the first batch of entities.\n *\n * The properties filter, sortField, query and sortFieldOrder, are going\n * to be immutable for the entire lifecycle of the following requests.\n *\n * @public\n */\nexport type QueryEntitiesInitialRequest = {\n fields?: string[];\n limit?: number;\n offset?: number;\n filter?: EntityFilterQuery;\n orderFields?: EntityOrderQuery;\n fullTextFilter?: {\n term: string;\n fields?: string[];\n };\n};\n\n/**\n * A request type for {@link CatalogClient.queryEntities}.\n * The method takes this type in a pagination request, following\n * the initial request.\n *\n * @public\n */\nexport type QueryEntitiesCursorRequest = {\n fields?: string[];\n limit?: number;\n cursor: string;\n};\n\n/**\n * The response type for {@link CatalogClient.queryEntities}.\n *\n * @public\n */\nexport type QueryEntitiesResponse = {\n /* The list of entities for the current request */\n items: Entity[];\n /* The number of entities among all the requests */\n totalItems: number;\n pageInfo: {\n /* The cursor for the next batch of entities */\n nextCursor?: string;\n /* The cursor for the previous batch of entities */\n prevCursor?: string;\n };\n};\n\n/**\n * A client for interacting with the Backstage software catalog through its API.\n *\n * @public\n */\nexport interface CatalogApi {\n /**\n * Lists catalog entities.\n *\n * @param request - Request parameters\n * @param options - Additional options\n */\n getEntities(\n request?: GetEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntitiesResponse>;\n\n /**\n * Gets a batch of entities, by their entity refs.\n *\n * @remarks\n *\n * The output list of entities is of the same size and in the same order as\n * the requested list of entity refs. Entries that are not found are returned\n * as null.\n *\n * @param request - Request parameters\n * @param options - Additional options\n */\n getEntitiesByRefs(\n request: GetEntitiesByRefsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntitiesByRefsResponse>;\n\n /**\n * Gets paginated entities from the catalog.\n *\n * @remarks\n *\n * @example\n *\n * ```\n * const response = await catalogClient.queryEntities({\n * filter: [{ kind: 'group' }],\n * limit: 20,\n * fullTextFilter: {\n * term: 'A',\n * },\n * orderFields: { field: 'metadata.name', order: 'asc' },\n * });\n * ```\n *\n * this will match all entities of type group having a name starting\n * with 'A', ordered by name ascending.\n *\n * The response will contain a maximum of 20 entities. In case\n * more than 20 entities exist, the response will contain a nextCursor\n * property that can be used to fetch the next batch of entities.\n *\n * ```\n * const secondBatchResponse = await catalogClient\n * .queryEntities({ cursor: response.nextCursor });\n * ```\n *\n * secondBatchResponse will contain the next batch of (maximum) 20 entities,\n * together with a prevCursor property, useful to fetch the previous batch.\n *\n * @public\n *\n * @param request - Request parameters\n * @param options - Additional options\n */\n queryEntities(\n request?: QueryEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<QueryEntitiesResponse>;\n\n /**\n * Gets entity ancestor information, i.e. the hierarchy of parent entities\n * whose processing resulted in a given entity appearing in the catalog.\n *\n * @param request - Request parameters\n * @param options - Additional options\n */\n getEntityAncestors(\n request: GetEntityAncestorsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntityAncestorsResponse>;\n\n /**\n * Gets a single entity from the catalog by its ref (kind, namespace, name)\n * triplet.\n *\n * @param entityRef - A complete entity ref, either on string or compound form\n * @param options - Additional options\n * @returns The matching entity, or undefined if there was no entity with that ref\n */\n getEntityByRef(\n entityRef: string | CompoundEntityRef,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined>;\n\n /**\n * Removes a single entity from the catalog by entity UID.\n *\n * @param uid - An entity UID\n * @param options - Additional options\n */\n removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n\n /**\n * Refreshes (marks for reprocessing) an entity in the catalog.\n *\n * @param entityRef - An entity ref on string form (e.g.\n * 'component/default:my-component')\n * @param options - Additional options\n */\n refreshEntity(\n entityRef: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n\n /**\n * Gets a summary of field facets of entities in the catalog.\n *\n * @param request - Request parameters\n * @param options - Additional options\n */\n getEntityFacets(\n request: GetEntityFacetsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntityFacetsResponse>;\n\n // Locations\n\n /**\n * List locations\n *\n * @param request - Request parameters\n * @param options - Additional options\n */\n getLocations(\n request?: {},\n options?: CatalogRequestOptions,\n ): Promise<GetLocationsResponse>;\n\n /**\n * Gets a registered location by its ID.\n *\n * @param id - A location ID\n * @param options - Additional options\n */\n getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n\n /**\n * Gets a registered location by its ref.\n *\n * @param locationRef - A location ref, e.g. \"url:https://github.com/...\"\n * @param options - Additional options\n */\n getLocationByRef(\n locationRef: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n\n /**\n * Registers a new location.\n *\n * @param location - Request parameters\n * @param options - Additional options\n */\n addLocation(\n location: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse>;\n\n /**\n * Removes a registered Location by its ID.\n *\n * @param id - A location ID\n * @param options - Additional options\n */\n removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void>;\n\n /**\n * Gets a location associated with an entity.\n *\n * @param entityRef - A complete entity ref, either on string or compound form\n * @param options - Additional options\n */\n getLocationByEntity(\n entityRef: string | CompoundEntityRef,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined>;\n\n /**\n * Validate entity and its location.\n *\n * @param entity - Entity to validate\n * @param locationRef - Location ref in format `url:http://example.com/file`\n * @param options - Additional options\n */\n validateEntity(\n entity: Entity,\n locationRef: string,\n options?: CatalogRequestOptions,\n ): Promise<ValidateEntityResponse>;\n\n /**\n * Validate a given location.\n *\n * @param location - Request parameters\n * @param options - Additional options\n */\n analyzeLocation(\n location: AnalyzeLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AnalyzeLocationResponse>;\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\n/**\n * The namespace that entities without an explicit namespace fall into.\n *\n * @public\n */\nexport const DEFAULT_NAMESPACE = 'default';\n\n/**\n * Annotation for linking to entity page from catalog pages.\n *\n * @public\n */\nexport const ANNOTATION_VIEW_URL = 'backstage.io/view-url';\n\n/**\n * Annotation for linking to entity edit page from catalog pages.\n *\n * @public\n */\nexport const ANNOTATION_EDIT_URL = 'backstage.io/edit-url';\n\n/**\n * Annotation for specifying the API server of a Kubernetes cluster\n *\n * @deprecated Import this constant from `@backstage/plugin-kubernetes-common` instead\n * @public\n */\nexport const ANNOTATION_KUBERNETES_API_SERVER = 'kubernetes.io/api-server';\n\n/**\n * Annotation for specifying the Certificate Authority of an API server for a Kubernetes cluster\n *\n * @deprecated Import this constant from `@backstage/plugin-kubernetes-common` instead\n * @public\n */\nexport const ANNOTATION_KUBERNETES_API_SERVER_CA =\n 'kubernetes.io/api-server-certificate-authority';\n\n/**\n * Annotation for specifying the auth provider for a Kubernetes cluster\n *\n * @deprecated Import this constant from `@backstage/plugin-kubernetes-common` instead\n * @public\n */\nexport const ANNOTATION_KUBERNETES_AUTH_PROVIDER =\n 'kubernetes.io/auth-provider';\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 { DEFAULT_NAMESPACE } from './constants';\nimport { CompoundEntityRef } from '../types';\nimport { Entity } from './Entity';\n\nfunction parseRefString(ref: string): {\n kind?: string;\n namespace?: string;\n name: string;\n} {\n let colonI = ref.indexOf(':');\n const slashI = ref.indexOf('/');\n\n // If the / is ahead of the :, treat the rest as the name\n if (slashI !== -1 && slashI < colonI) {\n colonI = -1;\n }\n\n const kind = colonI === -1 ? undefined : ref.slice(0, colonI);\n const namespace = slashI === -1 ? undefined : ref.slice(colonI + 1, slashI);\n const name = ref.slice(Math.max(colonI + 1, slashI + 1));\n\n if (kind === '' || namespace === '' || name === '') {\n throw new TypeError(\n `Entity reference \"${ref}\" was not on the form [<kind>:][<namespace>/]<name>`,\n );\n }\n\n return { kind, namespace, name };\n}\n\n/**\n * Extracts the kind, namespace and name that form the compound entity ref\n * triplet of the given entity.\n *\n * @public\n * @param entity - An entity\n * @returns The compound entity ref\n */\nexport function getCompoundEntityRef(entity: Entity): CompoundEntityRef {\n return {\n kind: entity.kind,\n namespace: entity.metadata.namespace || DEFAULT_NAMESPACE,\n name: entity.metadata.name,\n };\n}\n\n/**\n * Parses an entity reference, either on string or compound form, and returns\n * a structure with a name, and optional kind and namespace.\n *\n * @remarks\n *\n * The context object can contain default values for the kind and namespace,\n * that will be used if the input reference did not specify any.\n *\n * @public\n * @param ref - The reference to parse\n * @param context - The context of defaults that the parsing happens within\n * @returns The compound form of the reference\n */\nexport function parseEntityRef(\n ref: string | { kind?: string; namespace?: string; name: string },\n context?: {\n /** The default kind, if none is given in the reference */\n defaultKind?: string;\n /** The default namespace, if none is given in the reference */\n defaultNamespace?: string;\n },\n): CompoundEntityRef {\n if (!ref) {\n throw new Error(`Entity reference must not be empty`);\n }\n\n const defaultKind = context?.defaultKind;\n const defaultNamespace = context?.defaultNamespace || DEFAULT_NAMESPACE;\n\n let kind: string | undefined;\n let namespace: string | undefined;\n let name: string | undefined;\n\n if (typeof ref === 'string') {\n const parsed = parseRefString(ref);\n kind = parsed.kind ?? defaultKind;\n namespace = parsed.namespace ?? defaultNamespace;\n name = parsed.name;\n } else {\n kind = ref.kind ?? defaultKind;\n namespace = ref.namespace ?? defaultNamespace;\n name = ref.name;\n }\n\n if (!kind) {\n const textual = JSON.stringify(ref);\n throw new Error(\n `Entity reference ${textual} had missing or empty kind (e.g. did not start with \"component:\" or similar)`,\n );\n } else if (!namespace) {\n const textual = JSON.stringify(ref);\n throw new Error(\n `Entity reference ${textual} had missing or empty namespace`,\n );\n } else if (!name) {\n const textual = JSON.stringify(ref);\n throw new Error(`Entity reference ${textual} had missing or empty name`);\n }\n\n return { kind, namespace, name };\n}\n\n/**\n * Takes an entity or entity name/reference, and returns the string form of an\n * entity ref.\n *\n * @remarks\n *\n * This function creates a canonical and unique reference to the entity, converting\n * all parts of the name to lowercase and inserts the default namespace if needed.\n * It is typically not the best way to represent the entity reference to the user.\n *\n * @public\n * @param ref - The reference to serialize\n * @returns The same reference on either string or compound form\n */\nexport function stringifyEntityRef(\n ref: Entity | { kind: string; namespace?: string; name: string },\n): string {\n let kind;\n let namespace;\n let name;\n\n if ('metadata' in ref) {\n kind = ref.kind;\n namespace = ref.metadata.namespace ?? DEFAULT_NAMESPACE;\n name = ref.metadata.name;\n } else {\n kind = ref.kind;\n namespace = ref.namespace ?? DEFAULT_NAMESPACE;\n name = ref.name;\n }\n\n return `${kind.toLocaleLowerCase('en-US')}:${namespace.toLocaleLowerCase(\n 'en-US',\n )}/${name.toLocaleLowerCase('en-US')}`;\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\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 * 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\n/**\n * Entity annotation containing the location from which the entity is sourced.\n *\n * @public\n */\nexport const ANNOTATION_LOCATION = 'backstage.io/managed-by-location';\n\n/**\n * Entity annotation containing the originally sourced location which ultimately\n * led to this entity being ingested.\n *\n * @public\n */\nexport const ANNOTATION_ORIGIN_LOCATION =\n 'backstage.io/managed-by-origin-location';\n\n/**\n * Entity annotation pointing to the source (e.g. source code repository root or\n * similar) for this entity.\n *\n * @public\n */\nexport const ANNOTATION_SOURCE_LOCATION = 'backstage.io/source-location';\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 '../entity/Entity';\nimport { stringifyEntityRef } from '../entity/ref';\nimport { ANNOTATION_LOCATION, ANNOTATION_SOURCE_LOCATION } from './annotation';\n\n// See https://github.com/facebook/react/blob/f0cf832e1d0c8544c36aa8b310960885a11a847c/packages/react-dom-bindings/src/shared/sanitizeURL.js\nconst scriptProtocolPattern =\n // eslint-disable-next-line no-control-regex\n /^[\\u0000-\\u001F ]*j[\\r\\n\\t]*a[\\r\\n\\t]*v[\\r\\n\\t]*a[\\r\\n\\t]*s[\\r\\n\\t]*c[\\r\\n\\t]*r[\\r\\n\\t]*i[\\r\\n\\t]*p[\\r\\n\\t]*t[\\r\\n\\t]*\\:/i;\n\n/**\n * Parses a string form location reference.\n *\n * @public\n * @param ref - A string-form location ref, e.g. `'url:https://host'`\n * @returns A location ref, e.g. `{ type: 'url', target: 'https://host' }`\n */\nexport function parseLocationRef(ref: string): {\n type: string;\n target: string;\n} {\n if (typeof ref !== 'string') {\n throw new TypeError(\n `Unable to parse location ref '${ref}', unexpected argument ${typeof ref}`,\n );\n }\n\n const splitIndex = ref.indexOf(':');\n if (splitIndex < 0) {\n throw new TypeError(\n `Unable to parse location ref '${ref}', expected '<type>:<target>', e.g. 'url:https://host/path'`,\n );\n }\n\n const type = ref.substring(0, splitIndex).trim();\n const target = ref.substring(splitIndex + 1).trim();\n\n if (!type || !target) {\n throw new TypeError(\n `Unable to parse location ref '${ref}', expected '<type>:<target>', e.g. 'url:https://host/path'`,\n );\n }\n\n if (type === 'http' || type === 'https') {\n throw new TypeError(\n `Invalid location ref '${ref}', please prefix it with 'url:', e.g. 'url:${ref}'`,\n );\n }\n\n if (scriptProtocolPattern.test(target)) {\n throw new TypeError(\n `Invalid location ref '${ref}', target is a javascript: URL`,\n );\n }\n\n return { type, target };\n}\n\n/**\n * Turns a location ref into its string form.\n *\n * @public\n * @param ref - A location ref, e.g. `{ type: 'url', target: 'https://host' }`\n * @returns A string-form location ref, e.g. `'url:https://host'`\n */\nexport function stringifyLocationRef(ref: {\n type: string;\n target: string;\n}): string {\n const { type, target } = ref;\n\n if (!type) {\n throw new TypeError(`Unable to stringify location ref, empty type`);\n } else if (!target) {\n throw new TypeError(`Unable to stringify location ref, empty target`);\n }\n\n if (scriptProtocolPattern.test(target)) {\n throw new TypeError(\n `Invalid location ref '${type}:${target}', target is a javascript: URL`,\n );\n }\n\n return `${type}:${target}`;\n}\n\n/**\n * Returns the source code location of the Entity, to the extent that one exists.\n *\n * @remarks\n *\n * If the returned location type is of type 'url', the target should be readable at least\n * using the UrlReader from `@backstage/backend-common`. If it is not of type 'url', the caller\n * needs to have explicit handling of each location type or signal that it is not supported.\n *\n * @public\n */\nexport function getEntitySourceLocation(entity: Entity): {\n type: string;\n target: string;\n} {\n const locationRef =\n entity.metadata?.annotations?.[ANNOTATION_SOURCE_LOCATION] ??\n entity.metadata?.annotations?.[ANNOTATION_LOCATION];\n\n if (!locationRef) {\n throw new Error(\n `Entity '${stringifyEntityRef(entity)}' is missing location`,\n );\n }\n\n return parseLocationRef(locationRef);\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 { useTheme } from '@material-ui/core/styles';\nimport type {} from 'react-syntax-highlighter';\nimport LightAsync from 'react-syntax-highlighter/dist/esm/light-async';\nimport dark from 'react-syntax-highlighter/dist/esm/styles/hljs/dark';\nimport docco from 'react-syntax-highlighter/dist/esm/styles/hljs/docco';\n\nimport { CopyTextButton } from '../CopyTextButton';\n\n/**\n * Properties for {@link CodeSnippet}\n *\n * @public\n */\nexport interface CodeSnippetProps {\n /**\n * Code Snippet text\n */\n text: string;\n /**\n * Language used by {@link CodeSnippetProps.text}\n */\n language: string;\n /**\n * Whether to show line number\n *\n * @remarks\n *\n * Default: false\n */\n showLineNumbers?: boolean;\n /**\n * Whether to show button to copy code snippet\n *\n * @remarks\n *\n * Default: false\n */\n showCopyCodeButton?: boolean;\n /**\n * Array of line numbers to highlight\n */\n highlightedNumbers?: number[];\n /**\n * Custom styles applied to code\n *\n * @remarks\n *\n * Passed to {@link https://react-syntax-highlighter.github.io/react-syntax-highlighter/ | react-syntax-highlighter}\n */\n customStyle?: any;\n}\n\n/**\n * Thin wrapper on top of {@link https://react-syntax-highlighter.github.io/react-syntax-highlighter/ | react-syntax-highlighter}\n * providing consistent theming and copy code button\n *\n * @public\n */\nexport function CodeSnippet(props: CodeSnippetProps) {\n const {\n text,\n language,\n showLineNumbers = false,\n highlightedNumbers,\n customStyle,\n showCopyCodeButton = false,\n } = props;\n const theme = useTheme();\n const mode = theme.palette.type === 'dark' ? dark : docco;\n const highlightColor = theme.palette.type === 'dark' ? '#256bf3' : '#e6ffed';\n\n return (\n <Box position=\"relative\">\n <LightAsync\n customStyle={customStyle}\n language={language}\n style={mode}\n showLineNumbers={showLineNumbers}\n wrapLines\n lineNumberStyle={{ color: theme.palette.textVerySubtle }}\n lineProps={(lineNumber: number) =>\n highlightedNumbers?.includes(lineNumber)\n ? {\n style: {\n backgroundColor: highlightColor,\n },\n }\n : {}\n }\n >\n {text}\n </LightAsync>\n {showCopyCodeButton && (\n <Box position=\"absolute\" top={0} right={0}>\n <CopyTextButton text={text} />\n </Box>\n )}\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 { errorApiRef, useApi } from '@backstage/core-plugin-api';\nimport IconButton from '@material-ui/core/IconButton';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport CopyIcon from '@material-ui/icons/FileCopy';\nimport { MouseEventHandler, useEffect, useState } from 'react';\nimport useCopyToClipboard from 'react-use/esm/useCopyToClipboard';\nimport { coreComponentsTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/**\n * Properties for {@link CopyTextButton}\n *\n * @public\n */\nexport interface CopyTextButtonProps {\n /**\n * The text to be copied\n */\n text: string;\n /**\n * Number of milliseconds that the tooltip is shown\n *\n * @remarks\n *\n * Default: 1000\n */\n tooltipDelay?: number;\n /**\n * Text to show in the tooltip when user has clicked the button\n *\n * @remarks\n *\n * Default: \"Text copied to clipboard\"\n */\n tooltipText?: string;\n\n /**\n * Text to use as aria-label prop on the button\n *\n * @remarks\n *\n * Default: \"Copy text\"\n */\n 'aria-label'?: string;\n}\n\n/**\n * Copy text button with visual feedback\n *\n * @public\n * @remarks\n *\n * Visual feedback takes form of:\n * - a hover color\n * - click ripple\n * - Tooltip shown when user has clicked\n *\n * @example\n *\n * ```\n * <CopyTextButton\n * text=\"My text that I want to be copied to the clipboard\"\n * arial-label=\"Accessible label for this button\" />\n * ```\n */\nexport function CopyTextButton(props: CopyTextButtonProps) {\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n const {\n text,\n tooltipDelay = 1000,\n tooltipText = t('copyTextButton.tooltipText'),\n 'aria-label': ariaLabel = 'Copy text',\n } = props;\n const errorApi = useApi(errorApiRef);\n const [open, setOpen] = useState(false);\n const [{ error }, copyToClipboard] = useCopyToClipboard();\n\n useEffect(() => {\n if (error) {\n errorApi.post(error);\n }\n }, [error, errorApi]);\n\n const handleCopyClick: MouseEventHandler = e => {\n e.stopPropagation();\n setOpen(true);\n copyToClipboard(text);\n };\n\n return (\n <>\n <Tooltip\n id=\"copy-test-tooltip\"\n title={tooltipText}\n placement=\"top\"\n leaveDelay={tooltipDelay}\n onClose={() => setOpen(false)}\n open={open}\n >\n <IconButton onClick={handleCopyClick} aria-label={ariaLabel}>\n <CopyIcon />\n </IconButton>\n </Tooltip>\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 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 List from '@material-ui/core/List';\nimport ListItem from '@material-ui/core/ListItem';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport { PropsWithChildren } from 'react';\nimport { CopyTextButton } from '../CopyTextButton';\nimport { WarningPanel } from '../WarningPanel';\n\n/** @public */\nexport type ErrorPanelClassKey = 'text' | 'divider';\n\nconst useStyles = makeStyles(\n theme => ({\n text: {\n fontFamily: 'monospace',\n whiteSpace: 'pre',\n overflowX: 'auto',\n marginRight: theme.spacing(2),\n },\n divider: {\n margin: theme.spacing(2),\n },\n }),\n { name: 'BackstageErrorPanel' },\n);\n\ntype ErrorListProps = {\n error: string;\n message: string;\n request?: string;\n stack?: string;\n json?: string;\n};\n\nconst ErrorList = ({\n error,\n message,\n stack,\n children,\n}: PropsWithChildren<ErrorListProps>) => {\n const classes = useStyles();\n\n return (\n <List dense>\n <ListItem alignItems=\"flex-start\">\n <ListItemText\n classes={{ secondary: classes.text }}\n primary=\"Error\"\n secondary={error}\n />\n <CopyTextButton text={error} />\n </ListItem>\n\n <ListItem alignItems=\"flex-start\">\n <ListItemText\n classes={{ secondary: classes.text }}\n primary=\"Message\"\n secondary={message}\n />\n <CopyTextButton text={message} />\n </ListItem>\n\n {stack && (\n <ListItem alignItems=\"flex-start\">\n <ListItemText\n classes={{ secondary: classes.text }}\n primary=\"Stack Trace\"\n secondary={stack}\n />\n <CopyTextButton text={stack} />\n </ListItem>\n )}\n\n {children}\n </List>\n );\n};\n\n/** @public */\nexport type ErrorPanelProps = {\n error: Error;\n defaultExpanded?: boolean;\n titleFormat?: string;\n title?: string;\n};\n\n/**\n * Renders a warning panel as the effect of an error.\n *\n * @public\n */\nexport function ErrorPanel(props: PropsWithChildren<ErrorPanelProps>) {\n const { title, error, defaultExpanded, titleFormat, children } = props;\n return (\n <WarningPanel\n severity=\"error\"\n title={title ?? error.message}\n defaultExpanded={defaultExpanded}\n titleFormat={titleFormat}\n >\n <ErrorList\n error={error.name}\n message={error.message}\n stack={error.stack}\n children={children}\n />\n </WarningPanel>\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 */\nimport {\n configApiRef,\n useAnalytics,\n useApi,\n useApp,\n} from '@backstage/core-plugin-api';\n// eslint-disable-next-line no-restricted-imports\nimport MaterialLink, {\n LinkProps as MaterialLinkProps,\n} from '@material-ui/core/Link';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport classnames from 'classnames';\nimport { trimEnd } from 'lodash';\nimport {\n ReactNode,\n ReactElement,\n MouseEvent as ReactMouseEvent,\n ElementType,\n forwardRef,\n} from 'react';\nimport {\n createRoutesFromChildren,\n Link as RouterLink,\n LinkProps as RouterLinkProps,\n Route,\n} from 'react-router-dom';\nimport OpenInNew from '@material-ui/icons/OpenInNew';\n\nexport function isReactRouterBeta(): boolean {\n const [obj] = createRoutesFromChildren(<Route index element={<div />} />);\n return !obj.index;\n}\n\n/** @public */\nexport type LinkClassKey = 'visuallyHidden' | 'externalLink';\n\nconst useStyles = makeStyles(\n theme => ({\n visuallyHidden: {\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(50%)',\n overflow: 'hidden',\n position: 'absolute',\n userSelect: 'none',\n whiteSpace: 'nowrap',\n height: 1,\n width: 1,\n },\n externalLink: {\n position: 'relative',\n },\n externalLinkIcon: {\n verticalAlign: 'bottom',\n marginLeft: theme.spacing(0.5),\n },\n }),\n { name: 'Link' },\n);\n\nconst ExternalLinkIcon = () => {\n const app = useApp();\n const Icon = app.getSystemIcon('externalLink') || OpenInNew;\n const classes = useStyles();\n return <Icon className={classes.externalLinkIcon} />;\n};\n\nexport const isExternalUri = (uri: string) => /^([a-z+.-]+):/.test(uri);\n\n// See https://github.com/facebook/react/blob/f0cf832e1d0c8544c36aa8b310960885a11a847c/packages/react-dom-bindings/src/shared/sanitizeURL.js\nconst scriptProtocolPattern =\n // eslint-disable-next-line no-control-regex\n /^[\\u0000-\\u001F ]*j[\\r\\n\\t]*a[\\r\\n\\t]*v[\\r\\n\\t]*a[\\r\\n\\t]*s[\\r\\n\\t]*c[\\r\\n\\t]*r[\\r\\n\\t]*i[\\r\\n\\t]*p[\\r\\n\\t]*t[\\r\\n\\t]*\\:/i;\n\n// We install this globally in order to prevent javascript: URL XSS attacks via window.open\nconst originalWindowOpen = window.open as typeof window.open & {\n __backstage?: true;\n};\nif (originalWindowOpen && !originalWindowOpen.__backstage) {\n const newOpen = function open(\n this: Window,\n ...args: Parameters<typeof window.open>\n ) {\n const url = String(args[0]);\n if (scriptProtocolPattern.test(url)) {\n throw new Error(\n 'Rejected window.open() with a javascript: URL as a security precaution',\n );\n }\n return originalWindowOpen.apply(this, args);\n };\n newOpen.__backstage = true;\n window.open = newOpen;\n}\n\nexport type LinkProps = Omit<MaterialLinkProps, 'to'> &\n Omit<RouterLinkProps, 'to'> & {\n to: string;\n component?: ElementType<any>;\n noTrack?: boolean;\n externalLinkIcon?: boolean;\n };\n\n/**\n * Returns the app base url that could be empty if the Config API is not properly implemented.\n * The only cases there would be no Config API are in tests and in storybook stories, and in those cases, it's unlikely that callers would rely on this subpath behavior.\n */\nconst useBaseUrl = () => {\n try {\n const config = useApi(configApiRef);\n return config.getOptionalString('app.baseUrl');\n } catch {\n return undefined;\n }\n};\n\n/**\n * Get the app base path from the configured app baseUrl.\n * The returned path does not have a trailing slash.\n */\nconst useBasePath = () => {\n // baseUrl can be specified as just a path\n const base = 'http://sample.dev';\n const url = useBaseUrl() ?? '/';\n const { pathname } = new URL(url, base);\n return trimEnd(pathname, '/');\n};\n\n/** @deprecated Remove once we no longer support React Router v6 beta */\nexport const useResolvedPath = (uri: LinkProps['to']) => {\n let resolvedPath = String(uri);\n\n const basePath = useBasePath();\n const external = isExternalUri(resolvedPath);\n const startsWithBasePath = resolvedPath.startsWith(basePath);\n\n if (!external && !startsWithBasePath) {\n resolvedPath = basePath.concat(resolvedPath);\n }\n\n return resolvedPath;\n};\n\n/**\n * Given a react node, try to retrieve its text content.\n */\nconst getNodeText = (node: ReactNode): string => {\n // If the node is an array of children, recurse and join.\n if (node instanceof Array) {\n return node.map(getNodeText).join(' ').trim();\n }\n\n // If the node is a react element, recurse on its children.\n if (typeof node === 'object' && node) {\n return getNodeText((node as ReactElement)?.props?.children);\n }\n\n // Base case: the node is just text. Return it.\n if (['string', 'number'].includes(typeof node)) {\n return String(node);\n }\n\n // Base case: just return an empty string.\n return '';\n};\n\n/**\n * Thin wrapper on top of material-ui's Link component, which...\n * - Makes the Link use react-router\n * - Captures Link clicks as analytics events.\n */\nexport const Link = forwardRef<any, LinkProps>(\n ({ onClick, noTrack, externalLinkIcon, ...props }, ref) => {\n const classes = useStyles();\n const analytics = useAnalytics();\n\n // Adding the base path to URLs breaks react-router v6 stable, so we only\n // do it for beta. The react router version won't change at runtime so it is\n // fine to ignore the rules of hooks.\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const to = isReactRouterBeta() ? useResolvedPath(props.to) : props.to;\n const linkText = getNodeText(props.children) || to;\n const external = isExternalUri(to);\n const newWindow = external && !!/^https?:/.exec(to);\n\n if (scriptProtocolPattern.test(to)) {\n throw new Error(\n 'Link component rejected javascript: URL as a security precaution',\n );\n }\n\n const handleClick = (event: ReactMouseEvent<any, MouseEvent>) => {\n onClick?.(event);\n if (!noTrack) {\n analytics.captureEvent('click', linkText, { attributes: { to } });\n }\n };\n\n return external ? (\n // External links\n <MaterialLink\n {...(newWindow ? { target: '_blank', rel: 'noopener' } : {})}\n {...props}\n {...(props['aria-label']\n ? { 'aria-label': `${props['aria-label']}, Opens in a new window` }\n : {})}\n ref={ref}\n href={to}\n onClick={handleClick}\n className={classnames(classes.externalLink, props.className)}\n >\n {props.children}\n {externalLinkIcon && <ExternalLinkIcon />}\n <Typography component=\"span\" className={classes.visuallyHidden}>\n , Opens in a new window\n </Typography>\n </MaterialLink>\n ) : (\n // Interact with React Router for internal links\n <MaterialLink\n {...props}\n ref={ref}\n component={RouterLink}\n to={to}\n onClick={handleClick}\n />\n );\n },\n) as (props: LinkProps) => JSX.Element;\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 { Link, LinkProps } from '../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 <Link 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 */\n\nimport { makeStyles } from '@material-ui/core/styles';\nimport ReactMarkdown, { Options } from 'react-markdown';\nimport gfm from 'remark-gfm';\nimport { Children, createElement } from 'react';\nimport { CodeSnippet } from '../CodeSnippet';\nimport { HeadingProps } from 'react-markdown/lib/ast-to-react';\n\nexport type MarkdownContentClassKey = 'markdown';\n\nconst useStyles = makeStyles(\n theme => ({\n markdown: {\n '& table': {\n borderCollapse: 'collapse',\n border: `1px solid ${theme.palette.border}`,\n },\n '& th, & td': {\n border: `1px solid ${theme.palette.border}`,\n padding: theme.spacing(1),\n },\n '& td': {\n wordBreak: 'break-word',\n overflow: 'hidden',\n verticalAlign: 'middle',\n lineHeight: '1',\n margin: 0,\n padding: theme.spacing(3, 2, 3, 2.5),\n borderBottom: 0,\n },\n '& th': {\n backgroundColor: theme.palette.background.paper,\n },\n '& tr': {\n backgroundColor: theme.palette.background.paper,\n },\n '& tr:nth-child(odd)': {\n backgroundColor: theme.palette.background.default,\n },\n\n '& a': {\n color: theme.palette.link,\n },\n '& img': {\n maxWidth: '100%',\n },\n },\n }),\n { name: 'BackstageMarkdownContent' },\n);\n\ntype Props = {\n content: string;\n dialect?: 'gfm' | 'common-mark';\n linkTarget?: Options['linkTarget'];\n transformLinkUri?: (href: string) => string;\n transformImageUri?: (href: string) => string;\n className?: string;\n};\n\nconst flatten = (text: string, child: any): string => {\n if (!child) return text;\n\n return typeof child === 'string'\n ? text + child\n : Children.toArray(child.props.children).reduce(flatten, text);\n};\n\nconst headingRenderer = ({ level, children }: HeadingProps) => {\n const childrenArray = Children.toArray(children);\n const text = childrenArray.reduce(flatten, '');\n const slug = text.toLocaleLowerCase('en-US').replace(/\\W/g, '-');\n return createElement(`h${level}`, { id: slug }, children);\n};\n\nconst components: Options['components'] = {\n code: ({ inline, className, children, ...props }) => {\n const text = String(children).replace(/\\n+$/, '');\n const match = /language-(\\w+)/.exec(className || '');\n return !inline && match ? (\n <CodeSnippet language={match[1]} text={text} />\n ) : (\n <code className={className} {...props}>\n {children}\n </code>\n );\n },\n h1: headingRenderer,\n h2: headingRenderer,\n h3: headingRenderer,\n h4: headingRenderer,\n h5: headingRenderer,\n h6: headingRenderer,\n};\n\n/**\n * Renders markdown with the default dialect {@link https://github.github.com/gfm/ | gfm - GitHub flavored Markdown} to backstage theme styled HTML.\n *\n * @remarks\n * If you just want to render to plain {@link https://commonmark.org/ | CommonMark}, set the dialect to `'common-mark'`\n */\nexport function MarkdownContent(props: Props) {\n const {\n content,\n dialect = 'gfm',\n linkTarget,\n transformLinkUri,\n transformImageUri,\n className,\n } = props;\n const classes = useStyles();\n return (\n <ReactMarkdown\n remarkPlugins={dialect === 'gfm' ? [gfm] : []}\n className={`${classes.markdown} ${className ?? ''}`.trim()}\n children={content}\n components={components}\n linkTarget={linkTarget}\n transformLinkUri={transformLinkUri}\n transformImageUri={transformImageUri}\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 LinearProgress, {\n LinearProgressProps,\n} from '@material-ui/core/LinearProgress';\nimport { useTheme } from '@material-ui/core/styles';\nimport { PropsWithChildren, useEffect, useState } from 'react';\n\nexport function Progress(props: PropsWithChildren<LinearProgressProps>) {\n const theme = useTheme();\n const [isVisible, setIsVisible] = useState(false);\n\n useEffect(() => {\n const handle = setTimeout(\n () => setIsVisible(true),\n theme.transitions.duration.short,\n );\n return () => clearTimeout(handle);\n }, [theme.transitions.duration.short]);\n\n return isVisible ? (\n <LinearProgress {...props} data-testid=\"progress\" />\n ) : (\n <Box display=\"none\" data-testid=\"progress\" />\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 */\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 { configApiRef, useApi, useApp } from '@backstage/core-plugin-api';\nimport Box from '@material-ui/core/Box';\nimport Button from '@material-ui/core/Button';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport IconButton from '@material-ui/core/IconButton';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport MenuList from '@material-ui/core/MenuList';\nimport Popover from '@material-ui/core/Popover';\nimport { Theme, makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport { ReactNode, Children, MouseEventHandler, useState } from 'react';\nimport { SupportItem, SupportItemLink, useSupportConfig } from '../../hooks';\nimport { HelpIcon } from '../../icons';\nimport { Link } from '../Link';\nimport { coreComponentsTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\ntype SupportButtonProps = {\n title?: string;\n items?: SupportItem[];\n children?: ReactNode;\n};\n\nexport type SupportButtonClassKey = 'popoverList';\n\nconst useStyles = makeStyles(\n {\n popoverList: {\n minWidth: 260,\n maxWidth: 400,\n },\n menuItem: {\n whiteSpace: 'normal',\n },\n },\n { name: 'BackstageSupportButton' },\n);\n\nconst SupportIcon = ({ icon }: { icon: string | undefined }) => {\n const app = useApp();\n const Icon = icon ? app.getSystemIcon(icon) ?? HelpIcon : HelpIcon;\n return <Icon />;\n};\n\nconst SupportLink = ({ link }: { link: SupportItemLink }) => (\n <Link to={link.url}>{link.title ?? link.url}</Link>\n);\n\nconst SupportListItem = ({ item }: { item: SupportItem }) => {\n return (\n <MenuItem button={false}>\n <ListItemIcon>\n <SupportIcon icon={item.icon} />\n </ListItemIcon>\n <ListItemText\n primary={item.title}\n secondary={item.links?.reduce<React.ReactNode[]>(\n (prev, link, idx) => [\n ...prev,\n idx > 0 && <br key={idx} />,\n <SupportLink link={link} key={link.url} />,\n ],\n [],\n )}\n />\n </MenuItem>\n );\n};\n\nexport function SupportButton(props: SupportButtonProps) {\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n const { title, items, children } = props;\n const { items: configItems } = useSupportConfig();\n\n const [popoverOpen, setPopoverOpen] = useState(false);\n const [anchorEl, setAnchorEl] = useState<Element | null>(null);\n const classes = useStyles();\n const supportConfig = useApi(configApiRef).getOptionalConfig('app.support');\n const isSmallScreen = useMediaQuery<Theme>(theme =>\n theme.breakpoints.down('sm'),\n );\n\n const onClickHandler: MouseEventHandler = event => {\n setAnchorEl(event.currentTarget);\n setPopoverOpen(true);\n };\n\n const popoverCloseHandler = () => {\n setPopoverOpen(false);\n };\n\n if (!supportConfig) {\n return null;\n }\n\n return (\n <>\n <Box display=\"flex\" ml={1}>\n {isSmallScreen ? (\n <IconButton\n color=\"primary\"\n size=\"small\"\n onClick={onClickHandler}\n data-testid=\"support-button\"\n aria-label=\"Support\"\n >\n <HelpIcon />\n </IconButton>\n ) : (\n <Button\n data-testid=\"support-button\"\n aria-label=\"Support\"\n color=\"primary\"\n onClick={onClickHandler}\n startIcon={<HelpIcon />}\n >\n {t('supportButton.title')}\n </Button>\n )}\n </Box>\n <Popover\n data-testid=\"support-button-popover\"\n open={popoverOpen}\n anchorEl={anchorEl}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'right',\n }}\n transformOrigin={{\n vertical: 'top',\n horizontal: 'right',\n }}\n onClose={popoverCloseHandler}\n >\n <MenuList\n className={classes.popoverList}\n autoFocusItem={Boolean(anchorEl)}\n >\n {title && (\n <MenuItem\n button={false}\n alignItems=\"flex-start\"\n className={classes.menuItem}\n >\n <Typography variant=\"subtitle1\">{title}</Typography>\n </MenuItem>\n )}\n {Children.map(children, (child, i) => (\n <MenuItem\n button={false}\n alignItems=\"flex-start\"\n key={`child-${i}`}\n className={classes.menuItem}\n >\n {child}\n </MenuItem>\n ))}\n {(items ?? configItems).map((item, i) => (\n <SupportListItem item={item} key={`item-${i}`} />\n ))}\n </MenuList>\n <DialogActions>\n <Button\n color=\"primary\"\n onClick={popoverCloseHandler}\n aria-label=\"Close\"\n >\n {t('supportButton.close')}\n </Button>\n </DialogActions>\n </Popover>\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 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 = 'root' | 'value' | 'heder' | '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 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}>\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' | 'title';\n\nconst useFilterStyles = makeStyles(\n theme => ({\n root: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\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.root}>\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 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 { makeStyles, darken, lighten, Theme } from '@material-ui/core/styles';\nimport Accordion from '@material-ui/core/Accordion';\nimport AccordionSummary from '@material-ui/core/AccordionSummary';\nimport AccordionDetails from '@material-ui/core/AccordionDetails';\nimport Grid from '@material-ui/core/Grid';\nimport Typography from '@material-ui/core/Typography';\nimport ErrorOutline from '@material-ui/icons/ErrorOutline';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { ReactNode } from 'react';\nimport { MarkdownContent } from '../MarkdownContent';\n\nconst getWarningTextColor = (\n severity: NonNullable<WarningProps['severity']>,\n theme: Theme,\n) => {\n const getColor = theme.palette.type === 'light' ? darken : lighten;\n return getColor(theme.palette[severity].light, 0.6);\n};\n\nconst getWarningBackgroundColor = (\n severity: NonNullable<WarningProps['severity']>,\n theme: Theme,\n) => {\n const getBackgroundColor = theme.palette.type === 'light' ? lighten : darken;\n return getBackgroundColor(theme.palette[severity].light, 0.9);\n};\n\nconst useErrorOutlineStyles = makeStyles(theme => ({\n root: {\n marginRight: theme.spacing(1),\n fill: ({ severity }: WarningProps) =>\n getWarningTextColor(\n severity as NonNullable<WarningProps['severity']>,\n theme,\n ),\n },\n}));\n\nconst ErrorOutlineStyled = ({ severity }: Pick<WarningProps, 'severity'>) => {\n const classes = useErrorOutlineStyles({ severity });\n return <ErrorOutline classes={classes} />;\n};\nconst ExpandMoreIconStyled = ({ severity }: Pick<WarningProps, 'severity'>) => {\n const classes = useErrorOutlineStyles({ severity });\n return <ExpandMoreIcon classes={classes} />;\n};\n\nexport type WarningPanelClassKey =\n | 'panel'\n | 'summary'\n | 'summaryText'\n | 'message'\n | 'details';\n\nconst useStyles = makeStyles(\n theme => ({\n panel: {\n backgroundColor: ({ severity }: WarningProps) =>\n getWarningBackgroundColor(\n severity as NonNullable<WarningProps['severity']>,\n theme,\n ),\n color: ({ severity }: WarningProps) =>\n getWarningTextColor(\n severity as NonNullable<WarningProps['severity']>,\n theme,\n ),\n verticalAlign: 'middle',\n },\n summary: {\n display: 'flex',\n flexDirection: 'row',\n },\n summaryText: {\n color: ({ severity }: WarningProps) =>\n getWarningTextColor(\n severity as NonNullable<WarningProps['severity']>,\n theme,\n ),\n fontWeight: theme.typography.fontWeightBold,\n },\n markdownContent: {\n '& p': {\n display: 'inline',\n },\n },\n message: {\n width: '100%',\n display: 'block',\n color: ({ severity }: WarningProps) =>\n getWarningTextColor(\n severity as NonNullable<WarningProps['severity']>,\n theme,\n ),\n backgroundColor: ({ severity }: WarningProps) =>\n getWarningBackgroundColor(\n severity as NonNullable<WarningProps['severity']>,\n theme,\n ),\n },\n details: {\n width: '100%',\n display: 'block',\n color: theme.palette.textContrast,\n backgroundColor: theme.palette.background.default,\n border: `1px solid ${theme.palette.border}`,\n padding: theme.spacing(2.0),\n fontFamily: 'sans-serif',\n },\n }),\n { name: 'BackstageWarningPanel' },\n);\n\nexport type WarningProps = {\n title?: string;\n severity?: 'warning' | 'error' | 'info';\n titleFormat?: string;\n message?: ReactNode;\n defaultExpanded?: boolean;\n children?: ReactNode;\n};\n\nconst capitalize = (s: string) => {\n return s.charAt(0).toLocaleUpperCase('en-US') + s.slice(1);\n};\n\n/**\n * Show a user friendly error message to a user similar to\n * ErrorPanel except that the warning panel only shows the warning message to\n * the user.\n *\n * @param severity - Ability to change the severity of the alert. Default value\n * \"warning\"\n * @param title - A title for the warning. If not supplied, \"Warning\" will be\n * used.\n * @param message - Optional more detailed user-friendly message elaborating on\n * the cause of the error.\n * @param children - Objects to provide context, such as a stack trace or detailed\n * error reporting. Will be available inside an unfolded accordion.\n */\nexport function WarningPanel(props: WarningProps) {\n const {\n severity = 'warning',\n title,\n titleFormat,\n message,\n children,\n defaultExpanded,\n } = props;\n const classes = useStyles({ severity });\n\n // If no severity or title provided, the heading will read simply \"Warning\"\n const subTitle = capitalize(severity) + (title ? `: ${title}` : '');\n\n return (\n <Accordion\n defaultExpanded={defaultExpanded ?? false}\n className={classes.panel}\n role=\"alert\"\n >\n <AccordionSummary\n expandIcon={<ExpandMoreIconStyled severity={severity} />}\n className={classes.summary}\n >\n <ErrorOutlineStyled severity={severity} />\n <Typography className={classes.summaryText} variant=\"subtitle1\">\n {titleFormat === 'markdown' ? (\n <MarkdownContent\n content={subTitle}\n className={classes.markdownContent}\n />\n ) : (\n subTitle\n )}\n </Typography>\n </AccordionSummary>\n {(message || children) && (\n <AccordionDetails>\n <Grid container>\n {message && (\n <Grid item xs={12}>\n <Typography className={classes.message} variant=\"body1\">\n {message}\n </Typography>\n </Grid>\n )}\n {children && (\n <Grid item xs={12} className={classes.details}>\n {children}\n </Grid>\n )}\n </Grid>\n </AccordionDetails>\n )}\n </Accordion>\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 { useApiHolder, configApiRef } from '@backstage/core-plugin-api';\nimport { coreComponentsTranslationRef } from '../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\nexport type SupportItemLink = {\n url: string;\n title: string;\n};\n\nexport type SupportItem = {\n title: string;\n icon?: string;\n links: SupportItemLink[];\n};\n\nexport type SupportConfig = {\n url: string;\n items: SupportItem[];\n};\n\nconst useDefaultSupportConfig = () => {\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n return {\n url: 'https://github.com/backstage/backstage/issues',\n items: [\n {\n title: t('supportConfig.default.title'),\n icon: 'warning',\n links: [\n {\n // TODO: Update to dedicated support page on backstage.io/docs\n title: t('supportConfig.default.linkTitle'),\n url: 'https://github.com/backstage/backstage/blob/master/app-config.yaml',\n },\n ],\n },\n ],\n };\n};\n\nexport function useSupportConfig(): SupportConfig {\n const apiHolder = useApiHolder();\n const config = apiHolder.get(configApiRef);\n const supportConfig = config?.getOptionalConfig('app.support');\n const defaultSupportConfig = useDefaultSupportConfig();\n\n if (!supportConfig) {\n return defaultSupportConfig;\n }\n\n return {\n url: supportConfig.getString('url'),\n items: supportConfig.getConfigArray('items').flatMap(itemConf => ({\n title: itemConf.getString('title'),\n icon: itemConf.getOptionalString('icon'),\n links: (itemConf.getOptionalConfigArray('links') ?? []).flatMap(\n linkConf => ({\n url: linkConf.getString('url'),\n title: linkConf.getOptionalString('title') ?? '',\n }),\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 { IconComponent, useApp } from '@backstage/core-plugin-api';\nimport MuiBrokenImageIcon from '@material-ui/icons/BrokenImage';\nimport { ComponentProps } from 'react';\n\n/**\n * @public\n * Props for the {@link @backstage/core-plugin-api#IconComponent} component.\n */\nexport type IconComponentProps = ComponentProps<IconComponent>;\n\n/**\n * @public\n * Props for the {@link AppIcon} component.\n */\nexport type AppIconProps = IconComponentProps & {\n // The key of the system icon to render.\n id: string;\n // An optional fallback icon component to render when the system icon is not found.\n // Default to () => null.\n Fallback?: IconComponent;\n};\n\n/**\n * @public\n * A component that renders a system icon by its id.\n */\nexport function AppIcon(props: AppIconProps) {\n const { id: key, Fallback = MuiBrokenImageIcon, ...rest } = props;\n const app = useApp();\n const Icon = app.getSystemIcon(key) ?? Fallback;\n return <Icon {...rest} />;\n}\n\n// Should match the list of overridable system icon keys in @backstage/core-app-api\n/**\n * Broken Image Icon\n * @public\n */\nexport function BrokenImageIcon(props: IconComponentProps) {\n return <AppIcon id=\"brokenImage\" {...props} />;\n}\n/** @public */\nexport function CatalogIcon(props: IconComponentProps) {\n return <AppIcon id=\"catalog\" {...props} />;\n}\n/** @public */\nexport function ChatIcon(props: IconComponentProps) {\n return <AppIcon id=\"chat\" {...props} />;\n}\n/** @public */\nexport function DashboardIcon(props: IconComponentProps) {\n return <AppIcon id=\"dashboard\" {...props} />;\n}\n/** @public */\nexport function DocsIcon(props: IconComponentProps) {\n return <AppIcon id=\"docs\" {...props} />;\n}\n/** @public */\nexport function EmailIcon(props: IconComponentProps) {\n return <AppIcon id=\"email\" {...props} />;\n}\n/** @public */\nexport function GitHubIcon(props: IconComponentProps) {\n return <AppIcon id=\"github\" {...props} />;\n}\n/** @public */\nexport function GroupIcon(props: IconComponentProps) {\n return <AppIcon id=\"group\" {...props} />;\n}\n/** @public */\nexport function HelpIcon(props: IconComponentProps) {\n return <AppIcon id=\"help\" {...props} />;\n}\n/** @public */\nexport function UserIcon(props: IconComponentProps) {\n return <AppIcon id=\"user\" {...props} />;\n}\n/** @public */\nexport function WarningIcon(props: IconComponentProps) {\n return <AppIcon id=\"warning\" {...props} />;\n}\n/** @public */\nexport function StarIcon(props: IconComponentProps) {\n return <AppIcon id=\"star\" {...props} />;\n}\n/** @public */\nexport function UnstarredIcon(props: IconComponentProps) {\n return <AppIcon id=\"unstarred\" {...props} />;\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 { makeStyles, Theme } from '@material-ui/core/styles';\nimport classNames from 'classnames';\nimport { PropsWithChildren } from 'react';\n\n/** @public */\nexport type BackstageContentClassKey = 'root' | 'stretch' | 'noPadding';\n\nconst useStyles = makeStyles(\n (theme: Theme) => ({\n root: {\n gridArea: 'pageContent',\n minWidth: 0,\n paddingTop: theme.spacing(3),\n paddingBottom: theme.spacing(3),\n paddingLeft: theme.spacing(2),\n paddingRight: theme.spacing(2),\n [theme.breakpoints.up('sm')]: {\n paddingLeft: theme.spacing(3),\n paddingRight: theme.spacing(3),\n },\n },\n stretch: {\n display: 'flex',\n flexDirection: 'column',\n flexGrow: 1,\n },\n noPadding: {\n padding: 0,\n },\n }),\n { name: 'BackstageContent' },\n);\n\ntype Props = {\n stretch?: boolean;\n noPadding?: boolean;\n className?: string;\n};\n\n/**\n * The main content part inside a {@link Page}.\n *\n * @public\n *\n */\n\nexport function Content(props: PropsWithChildren<Props>) {\n const { className, stretch, noPadding, children, ...restProps } = props;\n\n const classes = useStyles();\n return (\n <article\n {...restProps}\n className={classNames(classes.root, className, {\n [classes.stretch]: stretch,\n [classes.noPadding]: noPadding,\n })}\n >\n {children}\n </article>\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 */\nimport Box from '@material-ui/core/Box';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport { PropsWithChildren, ReactNode } from 'react';\nimport { Helmet } from 'react-helmet';\n\n/**\n * TODO: favoriteable capability\n */\n\n/** @public */\nexport type ContentHeaderClassKey =\n | 'container'\n | 'leftItemsBox'\n | 'rightItemsBox'\n | 'description'\n | 'title';\n\nconst useStyles = (props: ContentHeaderProps) =>\n makeStyles(\n theme => ({\n container: {\n width: '100%',\n display: 'flex',\n flexDirection: 'row',\n flexWrap: 'wrap',\n justifyContent: 'flex-end',\n alignItems: 'center',\n marginBottom: theme.spacing(2),\n textAlign: props.textAlign,\n },\n leftItemsBox: {\n flex: '1 1 auto',\n minWidth: 0,\n overflow: 'visible',\n },\n rightItemsBox: {\n flex: '0 1 auto',\n display: 'flex',\n flexDirection: 'row',\n flexWrap: 'wrap',\n alignItems: 'center',\n marginLeft: theme.spacing(1),\n minWidth: 0,\n overflow: 'visible',\n },\n description: {},\n title: {\n display: 'inline-flex',\n marginBottom: 0,\n },\n }),\n { name: 'BackstageContentHeader' },\n );\n\ntype ContentHeaderTitleProps = {\n title?: string;\n className?: string;\n};\n\nconst ContentHeaderTitle = ({ title, className }: ContentHeaderTitleProps) => (\n <Typography\n variant=\"h4\"\n component=\"h2\"\n className={className}\n data-testid=\"header-title\"\n >\n {title}\n </Typography>\n);\n\ntype ContentHeaderDescriptionProps = {\n description?: string;\n className?: string;\n};\n\nconst ContentHeaderDescription = ({\n description,\n className,\n}: ContentHeaderDescriptionProps) =>\n description ? (\n <Typography\n variant=\"body2\"\n className={className}\n data-testid=\"header-description\"\n >\n {description}\n </Typography>\n ) : null;\n\ntype ContentHeaderProps = {\n title?: ContentHeaderTitleProps['title'];\n titleComponent?: ReactNode;\n description?: ContentHeaderDescriptionProps['description'];\n descriptionComponent?: ReactNode;\n textAlign?: 'left' | 'right' | 'center';\n};\n\n/**\n * A header at the top inside a {@link Content}.\n *\n * @public\n *\n */\n\nexport function ContentHeader(props: PropsWithChildren<ContentHeaderProps>) {\n const {\n description,\n title,\n titleComponent: TitleComponent = undefined,\n children,\n descriptionComponent: DescriptionComponent = undefined,\n textAlign = 'left',\n } = props;\n const classes = useStyles({ textAlign })();\n\n const renderedTitle = TitleComponent ? (\n TitleComponent\n ) : (\n <ContentHeaderTitle title={title} className={classes.title} />\n );\n\n const renderedDescription = DescriptionComponent ? (\n DescriptionComponent\n ) : (\n <ContentHeaderDescription\n description={description}\n className={classes.description}\n />\n );\n\n return (\n <>\n <Helmet title={title} />\n <Box className={classes.container}>\n <Box className={classes.leftItemsBox}>\n {renderedTitle}\n {renderedDescription}\n </Box>\n <Box className={classes.rightItemsBox}>{children}</Box>\n </Box>\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 { makeStyles } from '@material-ui/core/styles';\nimport MicDropSvgUrl from './mic-drop.svg';\n\nconst useStyles = makeStyles(\n theme => ({\n micDrop: {\n maxWidth: '60%',\n bottom: theme.spacing(2),\n right: theme.spacing(2),\n [theme.breakpoints.down('xs')]: {\n maxWidth: '96%',\n bottom: 'unset',\n right: 'unset',\n margin: theme.spacing(10, 'auto', 4),\n },\n },\n }),\n { name: 'BackstageErrorPageMicDrop' },\n);\n\nexport type MicDropClassKey = 'micDrop';\n\nexport const MicDrop = () => {\n const classes = useStyles();\n return (\n <img\n src={MicDropSvgUrl}\n className={classes.micDrop}\n alt=\"Girl dropping mic from her hands\"\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 */\nimport Typography from '@material-ui/core/Typography';\nimport { useState } from 'react';\nimport { Link } from '../../components/Link';\nimport { CodeSnippet } from '../../components';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { coreComponentsTranslationRef } from '../../translation';\n\ninterface IStackDetailsProps {\n stack: string;\n}\n\n/** @public */\nexport type StackDetailsClassKey = 'title';\n\nconst useStyles = makeStyles(\n theme => ({\n title: {\n paddingBottom: theme.spacing(5),\n [theme.breakpoints.down('xs')]: {\n paddingBottom: theme.spacing(4),\n fontSize: theme.typography.h3.fontSize,\n },\n },\n }),\n { name: 'BackstageErrorPageStackDetails' },\n);\n\n/**\n * Error page details with stack trace\n *\n * @public\n *\n */\nexport function StackDetails(props: IStackDetailsProps) {\n const { stack } = props;\n const classes = useStyles();\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n\n const [detailsOpen, setDetailsOpen] = useState<boolean>(false);\n\n if (!detailsOpen) {\n return (\n <Typography variant=\"h6\" className={classes.title}>\n <Link to=\"#\" onClick={() => setDetailsOpen(true)}>\n {t('errorPage.showMoreDetails')}\n </Link>\n </Typography>\n );\n }\n\n return (\n <>\n <Typography variant=\"h6\" className={classes.title}>\n <Link to=\"#\" onClick={() => setDetailsOpen(false)}>\n {t('errorPage.showLessDetails')}\n </Link>\n </Typography>\n <CodeSnippet\n text={stack}\n language=\"text\"\n showCopyCodeButton\n showLineNumbers\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 Grid from '@material-ui/core/Grid';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport { ReactNode } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { Link } from '../../components/Link';\nimport { useSupportConfig } from '../../hooks';\nimport { MicDrop } from './MicDrop';\nimport { StackDetails } from './StackDetails';\nimport { coreComponentsTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\ninterface IErrorPageProps {\n status?: string;\n statusMessage: string;\n additionalInfo?: ReactNode;\n supportUrl?: string;\n stack?: string;\n}\n\n/** @public */\nexport type ErrorPageClassKey = 'container' | 'title' | 'subtitle';\n\nconst useStyles = makeStyles(\n theme => ({\n container: {\n padding: theme.spacing(8),\n [theme.breakpoints.down('xs')]: {\n padding: theme.spacing(2),\n },\n },\n title: {\n paddingBottom: theme.spacing(5),\n [theme.breakpoints.down('xs')]: {\n paddingBottom: theme.spacing(4),\n fontSize: theme.typography.h3.fontSize,\n },\n },\n subtitle: {\n color: theme.palette.textSubtle,\n },\n }),\n { name: 'BackstageErrorPage' },\n);\n\n/**\n * Error page with status and description\n *\n * @public\n *\n */\nexport function ErrorPage(props: IErrorPageProps) {\n const {\n status = '',\n statusMessage,\n additionalInfo,\n supportUrl,\n stack,\n } = props;\n const classes = useStyles();\n const navigate = useNavigate();\n const support = useSupportConfig();\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n\n return (\n <Grid container className={classes.container}>\n <Grid item xs={12} sm={8} md={4}>\n <Typography\n data-testid=\"error\"\n variant=\"body1\"\n className={classes.subtitle}\n >\n {t('errorPage.subtitle', { status, statusMessage })}\n </Typography>\n <Typography variant=\"body1\" className={classes.subtitle}>\n {additionalInfo}\n </Typography>\n <Typography variant=\"h2\" className={classes.title}>\n {t('errorPage.title')}\n </Typography>\n <Typography variant=\"h6\" className={classes.title}>\n <Link to=\"#\" data-testid=\"go-back-link\" onClick={() => navigate(-1)}>\n {t('errorPage.goBack')}\n </Link>\n ... or please{' '}\n <Link to={supportUrl || support.url}>contact support</Link> if you\n think this is a bug.\n </Typography>\n {stack && <StackDetails stack={stack} />}\n </Grid>\n <MicDrop />\n </Grid>\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 MaterialBreadcrumbs from '@material-ui/core/Breadcrumbs';\nimport List from '@material-ui/core/List';\nimport ListItem from '@material-ui/core/ListItem';\nimport Popover from '@material-ui/core/Popover';\nimport { withStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport {\n MouseEvent,\n useState,\n Children,\n ComponentProps,\n Fragment,\n} from 'react';\n\ntype Props = ComponentProps<typeof MaterialBreadcrumbs>;\n\n/** @public */\nexport type BreadcrumbsClickableTextClassKey = 'root';\n\nconst ClickableText = withStyles(\n {\n root: {\n textDecoration: 'underline',\n cursor: 'pointer',\n },\n },\n { name: 'BackstageBreadcrumbsClickableText' },\n)(Typography);\n\n/** @public */\nexport type BreadcrumbsStyledBoxClassKey = 'root';\n\nconst StyledBox = withStyles(\n {\n root: {\n textDecoration: 'underline',\n color: 'inherit',\n },\n },\n { name: 'BackstageBreadcrumbsStyledBox' },\n)(Box);\n\n/** @public */\nexport type BreadcrumbsCurrentPageClassKey = 'root';\n\nconst BreadcrumbsCurrentPage = withStyles(\n {\n root: {\n fontStyle: 'italic',\n },\n },\n { name: 'BreadcrumbsCurrentPage' },\n)(Box);\n\n/**\n * Breadcrumbs component to show navigation hierarchical structure\n *\n * @public\n *\n */\nexport function Breadcrumbs(props: Props) {\n const { children, ...restProps } = props;\n const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);\n\n const childrenArray = Children.toArray(children);\n\n const [firstPage, secondPage, ...expandablePages] = childrenArray;\n const currentPage = expandablePages.length\n ? expandablePages.pop()\n : childrenArray[childrenArray.length - 1];\n const hasHiddenBreadcrumbs = childrenArray.length > 3;\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n setAnchorEl(event.currentTarget);\n };\n\n const handleClose = () => {\n setAnchorEl(null);\n };\n\n const open = Boolean(anchorEl);\n return (\n <Fragment>\n <MaterialBreadcrumbs aria-label=\"breadcrumb\" {...restProps}>\n {childrenArray.length > 1 && <StyledBox clone>{firstPage}</StyledBox>}\n {childrenArray.length > 2 && <StyledBox clone>{secondPage}</StyledBox>}\n {hasHiddenBreadcrumbs && (\n <ClickableText onClick={handleClick}>...</ClickableText>\n )}\n <BreadcrumbsCurrentPage>{currentPage}</BreadcrumbsCurrentPage>\n </MaterialBreadcrumbs>\n <Popover\n open={open}\n anchorEl={anchorEl}\n onClose={handleClose}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'left',\n }}\n transformOrigin={{\n vertical: 'top',\n horizontal: 'left',\n }}\n >\n <List>\n {expandablePages.map((pageLink, index) => (\n <ListItem key={index} button>\n <StyledBox clone>{pageLink}</StyledBox>\n </ListItem>\n ))}\n </List>\n </Popover>\n </Fragment>\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 { configApiRef, useApi } from '@backstage/core-plugin-api';\nimport Box from '@material-ui/core/Box';\nimport Grid from '@material-ui/core/Grid';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport Typography from '@material-ui/core/Typography';\nimport { CSSProperties, PropsWithChildren, ReactNode } from 'react';\nimport { Helmet } from 'react-helmet';\nimport { Link } from '../../components/Link';\nimport { Breadcrumbs } from '../Breadcrumbs';\nimport { useContent } from '../Sidebar';\n\n/** @public */\nexport type HeaderClassKey =\n | 'header'\n | 'leftItemsBox'\n | 'rightItemsBox'\n | 'title'\n | 'subtitle'\n | 'type'\n | 'breadcrumb'\n | 'breadcrumbType'\n | 'breadcrumbTitle';\n\nconst useStyles = makeStyles(\n theme => ({\n header: {\n gridArea: 'pageHeader',\n padding: theme.spacing(3),\n width: '100%',\n boxShadow: theme.shadows[4],\n position: 'relative',\n zIndex: 100,\n display: 'flex',\n flexDirection: 'row',\n alignItems: 'center',\n backgroundImage: theme.page.backgroundImage,\n backgroundPosition: 'center',\n backgroundSize: 'cover',\n [theme.breakpoints.down('sm')]: {\n flexWrap: 'wrap',\n },\n },\n leftItemsBox: {\n maxWidth: '100%',\n flexGrow: 1,\n },\n rightItemsBox: {\n width: 'auto',\n alignItems: 'center',\n },\n title: {\n color: theme.page.fontColor,\n wordBreak: 'break-word',\n fontSize: theme.typography.h3.fontSize,\n marginBottom: 0,\n },\n subtitle: {\n color: theme.page.fontColor,\n opacity: 0.8,\n display: 'inline-block', // prevents margin collapse of adjacent siblings\n marginTop: theme.spacing(1),\n maxWidth: '75ch',\n },\n type: {\n textTransform: 'uppercase',\n fontSize: 11,\n opacity: 0.8,\n marginBottom: theme.spacing(1),\n color: theme.page.fontColor,\n },\n breadcrumb: {\n color: theme.page.fontColor,\n },\n breadcrumbType: {\n fontSize: 'inherit',\n opacity: 0.7,\n marginRight: -theme.spacing(0.3),\n marginBottom: theme.spacing(0.3),\n },\n breadcrumbTitle: {\n fontSize: 'inherit',\n marginLeft: -theme.spacing(0.3),\n marginBottom: theme.spacing(0.3),\n },\n }),\n { name: 'BackstageHeader' },\n);\n\ntype HeaderStyles = ReturnType<typeof useStyles>;\n\ntype Props = {\n component?: ReactNode;\n pageTitleOverride?: string;\n style?: CSSProperties;\n subtitle?: ReactNode;\n title: ReactNode;\n tooltip?: string;\n type?: string;\n typeLink?: string;\n};\n\ntype TypeFragmentProps = {\n classes: HeaderStyles;\n pageTitle: string | ReactNode;\n type?: Props['type'];\n typeLink?: Props['typeLink'];\n};\n\ntype TitleFragmentProps = {\n classes: HeaderStyles;\n pageTitle: string | ReactNode;\n tooltip?: Props['tooltip'];\n};\n\ntype SubtitleFragmentProps = {\n classes: HeaderStyles;\n subtitle?: Props['subtitle'];\n};\n\nconst TypeFragment = ({\n type,\n typeLink,\n classes,\n pageTitle,\n}: TypeFragmentProps) => {\n if (!type) {\n return null;\n }\n\n if (!typeLink) {\n return <Typography className={classes.type}>{type}</Typography>;\n }\n\n return (\n <Breadcrumbs className={classes.breadcrumb}>\n <Link to={typeLink}>{type}</Link>\n <Typography>{pageTitle}</Typography>\n </Breadcrumbs>\n );\n};\n\nconst TitleFragment = ({ pageTitle, classes, tooltip }: TitleFragmentProps) => {\n const { contentRef } = useContent();\n\n const FinalTitle = (\n <Typography\n ref={contentRef}\n tabIndex={-1}\n className={classes.title}\n variant=\"h1\"\n >\n {pageTitle}\n </Typography>\n );\n\n if (!tooltip) {\n return FinalTitle;\n }\n\n return (\n <Tooltip title={tooltip} placement=\"top-start\">\n {FinalTitle}\n </Tooltip>\n );\n};\n\nconst SubtitleFragment = ({ classes, subtitle }: SubtitleFragmentProps) => {\n if (!subtitle) {\n return null;\n }\n\n if (typeof subtitle !== 'string') {\n return <>{subtitle}</>;\n }\n\n return (\n <Typography\n className={classes.subtitle}\n variant=\"subtitle2\"\n component=\"span\"\n >\n {subtitle}\n </Typography>\n );\n};\n/**\n * Backstage main header with abstract color background in multiple variants\n *\n * @public\n *\n */\nexport function Header(props: PropsWithChildren<Props>) {\n const {\n children,\n pageTitleOverride,\n style,\n subtitle,\n title,\n tooltip,\n type,\n typeLink,\n } = props;\n const classes = useStyles();\n const configApi = useApi(configApiRef);\n const appTitle = configApi.getOptionalString('app.title') || 'Backstage';\n const documentTitle = pageTitleOverride || title;\n const pageTitle = title || pageTitleOverride;\n const titleTemplate = `${documentTitle} | %s | ${appTitle}`;\n const defaultTitle = `${documentTitle} | ${appTitle}`;\n\n return (\n <>\n <Helmet titleTemplate={titleTemplate} defaultTitle={defaultTitle} />\n <header style={style} className={classes.header}>\n <Box className={classes.leftItemsBox}>\n <TypeFragment\n classes={classes}\n type={type}\n typeLink={typeLink}\n pageTitle={pageTitle}\n />\n <TitleFragment\n classes={classes}\n pageTitle={pageTitle}\n tooltip={tooltip}\n />\n <SubtitleFragment classes={classes} subtitle={subtitle} />\n </Box>\n <Grid container className={classes.rightItemsBox} spacing={4}>\n {children}\n </Grid>\n </header>\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 { ReactNode } from 'react';\nimport { makeStyles, Theme, ThemeProvider } from '@material-ui/core/styles';\nimport classNames from 'classnames';\n\nexport type PageClassKey = 'root';\n\nconst useStyles = makeStyles(\n theme => ({\n root: {\n display: 'grid',\n gridTemplateAreas:\n \"'pageHeader pageHeader pageHeader' 'pageSubheader pageSubheader pageSubheader' 'pageNav pageContent pageSidebar'\",\n gridTemplateRows: 'max-content auto 1fr',\n gridTemplateColumns: 'auto 1fr auto',\n overflowY: 'auto',\n height: '100vh',\n [theme.breakpoints.down('xs')]: {\n height: '100%',\n },\n '@media print': {\n display: 'block',\n height: 'auto',\n overflowY: 'inherit',\n },\n },\n }),\n { name: 'BackstagePage' },\n);\n\ntype Props = {\n themeId: string;\n className?: string;\n children?: ReactNode;\n};\n\nexport function Page(props: Props) {\n const { themeId, className, children } = props;\n const classes = useStyles();\n return (\n <ThemeProvider\n theme={(baseTheme: Theme) => ({\n ...baseTheme,\n page: baseTheme.getPageTheme({ themeId }),\n })}\n >\n <main className={classNames(classes.root, className)}>{children}</main>\n </ThemeProvider>\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 { PropsWithChildren, ComponentProps } from 'react';\n\nimport { Header } from '../Header';\nimport { Page } from './Page';\n\ntype PageWithHeaderProps = ComponentProps<typeof Header> & {\n themeId: string;\n};\n\nexport function PageWithHeader(props: PropsWithChildren<PageWithHeaderProps>) {\n const { themeId, children, ...restProps } = props;\n return (\n <Page themeId={themeId}>\n <Header {...restProps} />\n {children}\n </Page>\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\nenum LocalStorageKeys {\n SIDEBAR_PIN_STATE = 'sidebarPinState',\n}\n\nexport const LocalStorage = {\n getSidebarPinState(): boolean {\n let value;\n try {\n value = JSON.parse(\n window.localStorage.getItem(LocalStorageKeys.SIDEBAR_PIN_STATE) ||\n 'true',\n );\n } catch {\n return true;\n }\n return !!value;\n },\n setSidebarPinState(state: boolean) {\n return window.localStorage.setItem(\n LocalStorageKeys.SIDEBAR_PIN_STATE,\n JSON.stringify(state),\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, Theme } from '@material-ui/core/styles';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport {\n ReactNode,\n MutableRefObject,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport { SidebarConfig, SidebarConfigContext } from './config';\nimport { LocalStorage } from './localStorage';\nimport { SidebarPinStateProvider } from './SidebarPinStateContext';\n\nexport type SidebarPageClassKey = 'root';\n\ntype StyleProps = { sidebarConfig: SidebarConfig; isPinned: boolean };\n\nconst useStyles = makeStyles<Theme, StyleProps>(\n theme => ({\n root: {\n width: '100%',\n transition: 'padding-left 0.1s ease-out',\n isolation: 'isolate',\n [theme.breakpoints.up('sm')]: {\n paddingLeft: (props: StyleProps) =>\n props.isPinned\n ? props.sidebarConfig.drawerWidthOpen\n : props.sidebarConfig.drawerWidthClosed,\n },\n [theme.breakpoints.down('xs')]: {\n paddingBottom: (props: StyleProps) =>\n props.sidebarConfig.mobileSidebarHeight,\n },\n '@media print': {\n padding: '0px !important',\n },\n },\n content: {\n zIndex: 0,\n isolation: 'isolate',\n '&:focus': {\n outline: 0,\n },\n },\n }),\n { name: 'BackstageSidebarPage' },\n);\n\n/**\n * Props for SidebarPage\n *\n * @public\n */\nexport type SidebarPageProps = {\n children?: ReactNode;\n};\n\ntype PageContextType = {\n content: {\n contentRef?: MutableRefObject<HTMLElement | null>;\n };\n};\n\nconst PageContext = createContext<PageContextType>({\n content: {\n contentRef: undefined,\n },\n});\nexport function SidebarPage(props: SidebarPageProps) {\n const [isPinned, setIsPinned] = useState(() =>\n LocalStorage.getSidebarPinState(),\n );\n const { sidebarConfig } = useContext(SidebarConfigContext);\n\n const contentRef = useRef(null);\n\n const pageContext = useMemo(\n () => ({\n content: {\n contentRef,\n },\n }),\n [contentRef],\n );\n\n useEffect(() => {\n LocalStorage.setSidebarPinState(isPinned);\n }, [isPinned]);\n\n const isMobile = useMediaQuery<Theme>(theme => theme.breakpoints.down('xs'), {\n noSsr: true,\n });\n\n const toggleSidebarPinState = () => setIsPinned(!isPinned);\n\n const classes = useStyles({ isPinned, sidebarConfig });\n\n return (\n <SidebarPinStateProvider\n value={{\n isPinned,\n toggleSidebarPinState,\n isMobile,\n }}\n >\n <PageContext.Provider value={pageContext}>\n <Box className={classes.root}>{props.children}</Box>\n </PageContext.Provider>\n </SidebarPinStateProvider>\n );\n}\n\n/**\n * This hook provides a react ref to the main content.\n * Allows to set an element as the main content and focus on that component.\n *\n * *Note: If `contentRef` is not set `focusContent` is noop. `Content` component sets this ref automatically*\n *\n * @public\n * @example\n * Focus current content\n * ```tsx\n * const { focusContent} = useContent();\n * ...\n * <Button onClick={focusContent}>\n * focus main content\n * </Button>\n * ```\n * @example\n * Set the reference to an Html element\n * ```\n * const { contentRef } = useContent();\n * ...\n * <article ref={contentRef} tabIndex={-1}>Main Content</article>\n * ```\n */\nexport function useContent() {\n const { content } = useContext(PageContext);\n\n const focusContent = useCallback(() => {\n content?.contentRef?.current?.focus();\n }, [content]);\n\n return { focusContent, contentRef: content?.contentRef };\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 */\n\nimport {\n createVersionedContext,\n createVersionedValueMap,\n} from '@backstage/version-bridge';\nimport { createContext, ReactNode, useContext } from 'react';\n\n/**\n * Type of `SidebarPinStateContext`\n *\n * @public\n * @deprecated Use `SidebarPinState` instead.\n */\nexport type SidebarPinStateContextType = {\n isPinned: boolean;\n toggleSidebarPinState: () => any;\n isMobile?: boolean;\n};\n\n/**\n * The pin state of the sidebar.\n *\n * @public\n */\nexport type SidebarPinState = {\n /**\n * Whether or not the sidebar is pinned to the `open` state. When `isPinned`\n * is `false`, the sidebar opens and closes on hover. When `true`, the\n * sidebar is permanently opened, regardless of user interaction.\n */\n isPinned: boolean;\n\n /**\n * A function to toggle the pin state of the sidebar.\n */\n toggleSidebarPinState: () => any;\n\n /**\n * Whether or not the sidebar is or should be rendered in a mobile-optimized\n * way.\n */\n isMobile?: boolean;\n};\n\nconst defaultSidebarPinStateContext = {\n isPinned: true,\n toggleSidebarPinState: () => {},\n isMobile: false,\n};\n\n/**\n * Contains the state on how the `Sidebar` is rendered\n *\n * @public @deprecated\n * Use `<SidebarPinStateContextProvider>` + `useSidebarPinState()` instead.\n */\nexport const LegacySidebarPinStateContext =\n createContext<SidebarPinStateContextType>(defaultSidebarPinStateContext);\n\nconst VersionedSidebarPinStateContext = createVersionedContext<{\n 1: SidebarPinState;\n}>('sidebar-pin-state-context');\n\n/**\n * Provides state for how the `Sidebar` is rendered\n *\n * @public\n */\nexport function SidebarPinStateProvider(props: {\n children: ReactNode;\n value: SidebarPinStateContextType;\n}) {\n const { children, value } = props;\n return (\n <LegacySidebarPinStateContext.Provider value={value}>\n <VersionedSidebarPinStateContext.Provider\n value={createVersionedValueMap({ 1: value })}\n >\n {children}\n </VersionedSidebarPinStateContext.Provider>\n </LegacySidebarPinStateContext.Provider>\n );\n}\n\n/**\n * Hook to read and update sidebar pin state, which controls whether or not the\n * sidebar is pinned open.\n *\n * @public\n */\nexport const useSidebarPinState = (): SidebarPinState => {\n const versionedPinStateContext = useContext(VersionedSidebarPinStateContext);\n const legacyPinStateContext = useContext(LegacySidebarPinStateContext);\n\n // Invoked from outside a SidebarPinStateProvider: check for the legacy\n // context's value, but otherwise return the default.\n if (versionedPinStateContext === undefined) {\n return legacyPinStateContext || defaultSidebarPinStateContext;\n }\n\n const pinStateContext = versionedPinStateContext.atVersion(1);\n if (pinStateContext === undefined) {\n throw new Error('No context found for version 1.');\n }\n\n return pinStateContext;\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 { createContext, Dispatch, SetStateAction } from 'react';\n\nconst drawerWidthClosed = 72;\nconst iconPadding = 24;\nconst userBadgePadding = 18;\n\n/** @public */\nexport type SidebarOptions = {\n drawerWidthClosed?: number;\n drawerWidthOpen?: number;\n};\n\n/** @public */\nexport type SubmenuOptions = {\n drawerWidthClosed?: number;\n drawerWidthOpen?: number;\n};\n\n/** @internal */\nexport type SidebarConfig = {\n drawerWidthClosed: number;\n drawerWidthOpen: number;\n defaultOpenDelayMs: number;\n defaultCloseDelayMs: number;\n defaultFadeDuration: number;\n logoHeight: number;\n iconContainerWidth: number;\n iconSize: number;\n iconPadding: number;\n selectedIndicatorWidth: number;\n userBadgePadding: number;\n userBadgeDiameter: number;\n mobileSidebarHeight: number;\n};\n\nexport const sidebarConfig = {\n drawerWidthClosed,\n drawerWidthOpen: 224,\n // As per NN/g's guidance on timing for exposing hidden content\n // See https://www.nngroup.com/articles/timing-exposing-content/\n defaultOpenDelayMs: 100,\n defaultCloseDelayMs: 0,\n defaultFadeDuration: 200,\n logoHeight: 32,\n iconContainerWidth: drawerWidthClosed,\n iconSize: drawerWidthClosed - iconPadding * 2,\n iconPadding,\n selectedIndicatorWidth: 3,\n userBadgePadding,\n userBadgeDiameter: drawerWidthClosed - userBadgePadding * 2,\n mobileSidebarHeight: 56,\n};\n\nexport const makeSidebarConfig = (\n customSidebarConfig: Partial<SidebarOptions>,\n) => ({\n ...sidebarConfig,\n ...customSidebarConfig,\n iconContainerWidth: sidebarConfig.drawerWidthClosed,\n iconSize: sidebarConfig.drawerWidthClosed - sidebarConfig.iconPadding * 2,\n userBadgeDiameter:\n sidebarConfig.drawerWidthClosed - sidebarConfig.userBadgePadding * 2,\n});\n\n/** @internal */\nexport type SubmenuConfig = {\n drawerWidthClosed: number;\n drawerWidthOpen: number;\n defaultOpenDelayMs: number;\n};\n\nexport const submenuConfig = {\n drawerWidthClosed: 0,\n drawerWidthOpen: 202,\n defaultOpenDelayMs: sidebarConfig.defaultOpenDelayMs + 200,\n};\n\nexport const makeSidebarSubmenuConfig = (\n customSubmenuConfig: Partial<SubmenuOptions>,\n) => ({\n ...submenuConfig,\n ...customSubmenuConfig,\n});\n\nexport const SIDEBAR_INTRO_LOCAL_STORAGE =\n '@backstage/core/sidebar-intro-dismissed';\n\nexport type SidebarConfigContextType = {\n sidebarConfig: SidebarConfig;\n submenuConfig: SubmenuConfig;\n};\n\nexport const SidebarConfigContext = createContext<SidebarConfigContextType>({\n sidebarConfig,\n submenuConfig,\n});\n\nexport type SidebarItemWithSubmenuContextType = {\n isHoveredOn: boolean;\n setIsHoveredOn: Dispatch<SetStateAction<boolean>>;\n};\n\nexport const SidebarItemWithSubmenuContext =\n createContext<SidebarItemWithSubmenuContextType>({\n isHoveredOn: false,\n setIsHoveredOn: () => {},\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 { createTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/** @alpha */\nexport const coreComponentsTranslationRef = createTranslationRef({\n id: 'core-components',\n messages: {\n signIn: {\n title: 'Sign In',\n loginFailed: 'Login failed',\n customProvider: {\n title: 'Custom User',\n subtitle:\n 'Enter your own User ID and credentials.\\n This selection will not be stored.',\n userId: 'User ID',\n tokenInvalid: 'Token is not a valid OpenID Connect JWT Token',\n continue: 'Continue',\n idToken: 'ID Token (optional)',\n },\n guestProvider: {\n title: 'Guest',\n subtitle:\n 'Enter as a Guest User.\\n You will not have a verified identity, meaning some features might be unavailable.',\n enter: 'Enter',\n },\n },\n skipToContent: 'Skip to content',\n copyTextButton: {\n tooltipText: 'Text copied to clipboard',\n },\n simpleStepper: {\n reset: 'Reset',\n finish: 'Finish',\n next: 'Next',\n skip: 'Skip',\n back: 'Back',\n },\n errorPage: {\n subtitle: 'ERROR {{status}}: {{statusMessage}}',\n title: 'Looks like someone dropped the mic!',\n goBack: 'Go back',\n showMoreDetails: 'Show more details',\n showLessDetails: 'Show less details',\n },\n emptyState: {\n missingAnnotation: {\n title: 'Missing Annotation',\n actionTitle:\n 'Add the annotation to your component YAML as shown in the highlighted example below:',\n readMore: 'Read more',\n },\n },\n supportConfig: {\n default: {\n title: 'Support Not Configured',\n linkTitle: 'Add `app.support` config key',\n },\n },\n errorBoundary: {\n title: 'Please contact {{slackChannel}} for help.',\n },\n oauthRequestDialog: {\n title: 'Login Required',\n authRedirectTitle: 'This will trigger a http redirect to OAuth Login.',\n login: 'Log in',\n rejectAll: 'Reject All',\n message:\n 'Sign-in to allow {{appTitle}} access to {{provider}} APIs and identities.',\n },\n supportButton: {\n title: 'Support',\n close: 'Close',\n },\n table: {\n filter: {\n title: 'Filters',\n clearAll: 'Clear all',\n placeholder: 'All results',\n },\n body: {\n emptyDataSourceMessage: 'No records to display',\n },\n pagination: {\n firstTooltip: 'First Page',\n labelDisplayedRows: '{from}-{to} of {count}',\n labelRowsSelect: 'rows',\n lastTooltip: 'Last Page',\n nextTooltip: 'Next Page',\n previousTooltip: 'Previous Page',\n },\n toolbar: {\n search: 'Filter',\n },\n header: {\n actions: 'Actions',\n },\n },\n alertDisplay: {\n message_one: '({{ count }} newer message)',\n message_other: '({{ count }} newer messages)',\n },\n autoLogout: {\n stillTherePrompt: {\n title: 'Logging out due to inactivity',\n buttonText: \"Yes! Don't log me out\",\n },\n },\n proxiedSignInPage: {\n title:\n 'You do not appear to be signed in. Please try reloading the browser page.',\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 createVersionedContext,\n createVersionedValueMap,\n} from '@backstage/version-bridge';\nimport { ComponentType, ReactNode, useContext } from 'react';\nimport { AnalyticsContextValue } from './types';\n\nconst AnalyticsReactContext = createVersionedContext<{\n 1: AnalyticsContextValue;\n}>('analytics-context');\n\n/**\n * A \"private\" (to this package) hook that enables context inheritance and a\n * way to read Analytics Context values at event capture-time.\n *\n * @internal\n */\nexport const useAnalyticsContext = (): AnalyticsContextValue => {\n const theContext = useContext(AnalyticsReactContext);\n\n // Provide a default value if no value exists.\n if (theContext === undefined) {\n return {\n routeRef: 'unknown',\n pluginId: 'root',\n extension: 'App',\n };\n }\n\n // This should probably never happen, but check for it.\n const theValue = theContext.atVersion(1);\n if (theValue === undefined) {\n throw new Error('No context found for version 1.');\n }\n\n return theValue;\n};\n\n/**\n * Provides components in the child react tree an Analytics Context, ensuring\n * all analytics events captured within the context have relevant attributes.\n *\n * @remarks\n *\n * Analytics contexts are additive, meaning the context ultimately emitted with\n * an event is the combination of all contexts in the parent tree.\n *\n * @public\n */\nexport const AnalyticsContext = (options: {\n attributes: Partial<AnalyticsContextValue>;\n children: ReactNode;\n}) => {\n const { attributes, children } = options;\n\n const parentValues = useAnalyticsContext();\n const combinedValue = {\n ...parentValues,\n ...attributes,\n };\n\n const versionedCombinedValue = createVersionedValueMap({ 1: combinedValue });\n return (\n <AnalyticsReactContext.Provider value={versionedCombinedValue}>\n {children}\n </AnalyticsReactContext.Provider>\n );\n};\n\n/**\n * Returns an HOC wrapping the provided component in an Analytics context with\n * the given values.\n *\n * @param Component - Component to be wrapped with analytics context attributes\n * @param values - Analytics context key/value pairs.\n * @internal\n */\nexport function withAnalyticsContext<TProps extends {}>(\n Component: ComponentType<TProps>,\n values: AnalyticsContextValue,\n) {\n const ComponentWithAnalyticsContext = (props: TProps) => {\n return (\n <AnalyticsContext attributes={values}>\n <Component {...props} />\n </AnalyticsContext>\n );\n };\n ComponentWithAnalyticsContext.displayName = `WithAnalyticsContext(${\n Component.displayName || Component.name || 'Component'\n })`;\n return ComponentWithAnalyticsContext;\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 { getOrCreateGlobalSingleton } from '@backstage/version-bridge';\nimport {\n AnalyticsApi,\n AnalyticsEventAttributes,\n AnalyticsTracker,\n} from '../apis';\nimport { AnalyticsContextValue } from './types';\n\ntype TempGlobalEvents = {\n /**\n * Stores the most recent \"gathered\" mountpoint navigation.\n */\n mostRecentGatheredNavigation?: {\n action: string;\n subject: string;\n value?: number;\n attributes?: AnalyticsEventAttributes;\n context: AnalyticsContextValue;\n };\n /**\n * Stores the most recent routable extension render.\n */\n mostRecentRoutableExtensionRender?: {\n context: AnalyticsContextValue;\n };\n /**\n * Tracks whether or not a beforeunload event listener has already been\n * registered.\n */\n beforeUnloadRegistered: boolean;\n};\n\n/**\n * Temporary global store for select event data. Used to make `navigate` events\n * more accurate when gathered mountpoints are used.\n */\nconst globalEvents = getOrCreateGlobalSingleton<TempGlobalEvents>(\n 'core-plugin-api:analytics-tracker-events',\n () => ({\n mostRecentGatheredNavigation: undefined,\n mostRecentRoutableExtensionRender: undefined,\n beforeUnloadRegistered: false,\n }),\n);\n\n/**\n * Internal-only event representing when a routable extension is rendered.\n */\nexport const routableExtensionRenderedEvent = '_ROUTABLE-EXTENSION-RENDERED';\n\nexport class Tracker implements AnalyticsTracker {\n constructor(\n private readonly analyticsApi: AnalyticsApi,\n private context: AnalyticsContextValue = {\n routeRef: 'unknown',\n pluginId: 'root',\n extension: 'App',\n },\n ) {\n // Only register a single beforeunload event across all trackers.\n if (!globalEvents.beforeUnloadRegistered) {\n // Before the page unloads, attempt to capture any deferred navigation\n // events that haven't yet been captured.\n addEventListener(\n 'beforeunload',\n () => {\n if (globalEvents.mostRecentGatheredNavigation) {\n this.analyticsApi.captureEvent({\n ...globalEvents.mostRecentGatheredNavigation,\n ...globalEvents.mostRecentRoutableExtensionRender,\n });\n globalEvents.mostRecentGatheredNavigation = undefined;\n globalEvents.mostRecentRoutableExtensionRender = undefined;\n }\n },\n { once: true, passive: true },\n );\n\n // Prevent duplicate handlers from being registered.\n globalEvents.beforeUnloadRegistered = true;\n }\n }\n\n setContext(context: AnalyticsContextValue) {\n this.context = context;\n }\n\n captureEvent(\n action: string,\n subject: string,\n {\n value,\n attributes,\n }: { value?: number; attributes?: AnalyticsEventAttributes } = {},\n ) {\n // Never pass internal \"_routeNodeType\" context value.\n const { _routeNodeType, ...context } = this.context;\n\n // Never fire the special \"_routable-extension-rendered\" internal event.\n if (action === routableExtensionRenderedEvent) {\n // But keep track of it if we're delaying a `navigate` event for a\n // a gathered route node type.\n if (globalEvents.mostRecentGatheredNavigation) {\n globalEvents.mostRecentRoutableExtensionRender = {\n context: {\n ...context,\n extension: 'App',\n },\n };\n }\n return;\n }\n\n // If we are about to fire a real event, and we have an un-fired gathered\n // mountpoint navigation on the global store, we need to fire the navigate\n // event first, so this real event happens accurately after the navigation.\n if (globalEvents.mostRecentGatheredNavigation) {\n try {\n this.analyticsApi.captureEvent({\n ...globalEvents.mostRecentGatheredNavigation,\n ...globalEvents.mostRecentRoutableExtensionRender,\n });\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn('Error during analytics event capture. %o', e);\n }\n\n // Clear the global stores.\n globalEvents.mostRecentGatheredNavigation = undefined;\n globalEvents.mostRecentRoutableExtensionRender = undefined;\n }\n\n // Never directly fire a navigation event on a gathered route with default\n // contextual details.\n if (\n action === 'navigate' &&\n _routeNodeType === 'gathered' &&\n context.pluginId === 'root'\n ) {\n // Instead, set it on the global store.\n globalEvents.mostRecentGatheredNavigation = {\n action,\n subject,\n value,\n attributes,\n context,\n };\n return;\n }\n\n try {\n this.analyticsApi.captureEvent({\n action,\n subject,\n value,\n attributes,\n context,\n });\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn('Error during analytics event capture. %o', e);\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 { useAnalyticsContext } from './AnalyticsContext';\nimport {\n analyticsApiRef,\n AnalyticsTracker,\n AnalyticsApi,\n useApi,\n} from '../apis';\nimport { useRef } from 'react';\nimport { Tracker } from './Tracker';\n\nfunction useAnalyticsApi(): AnalyticsApi {\n try {\n return useApi(analyticsApiRef);\n } catch {\n return { captureEvent: () => {} };\n }\n}\n\n/**\n * Gets a pre-configured analytics tracker.\n *\n * @public\n */\nexport function useAnalytics(): AnalyticsTracker {\n const trackerRef = useRef<Tracker | null>(null);\n const context = useAnalyticsContext();\n // Our goal is to make this API truly optional for any/all consuming code\n // (including tests). This hook runs last to ensure hook order is, as much as\n // possible, maintained.\n const analyticsApi = useAnalyticsApi();\n\n function getTracker(): Tracker {\n if (trackerRef.current === null) {\n trackerRef.current = new Tracker(analyticsApi);\n }\n return trackerRef.current;\n }\n\n const tracker = getTracker();\n // this is not ideal, but it allows to memoize the tracker\n // without explicitly set the context as dependency.\n tracker.setContext(context);\n\n return tracker;\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 { createApiRef, ApiRef } from '../system';\nimport { Observable } from '@backstage/types';\n\n/**\n * Message handled by the {@link AlertApi}.\n *\n * @public\n */\nexport type AlertMessage = {\n message: string;\n // Severity will default to success since that is what material ui defaults the value to.\n severity?: 'success' | 'info' | 'warning' | 'error';\n display?: 'permanent' | 'transient';\n};\n\n/**\n * The alert API is used to report alerts to the app, and display them to the user.\n *\n * @public\n */\nexport type AlertApi = {\n /**\n * Post an alert for handling by the application.\n */\n post(alert: AlertMessage): void;\n\n /**\n * Observe alerts posted by other parts of the application.\n */\n alert$(): Observable<AlertMessage>;\n};\n\n/**\n * The {@link ApiRef} of {@link AlertApi}.\n *\n * @public\n */\nexport const alertApiRef: ApiRef<AlertApi> = createApiRef({\n id: 'core.alert',\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 { ApiRef, createApiRef } from '../system';\nimport { AnalyticsContextValue } from '../../analytics/types';\n\n/**\n * Represents an event worth tracking in an analytics system that could inform\n * how users of a Backstage instance are using its features.\n *\n * @public\n */\nexport type AnalyticsEvent = {\n /**\n * A string that identifies the event being tracked by the type of action the\n * event represents. Be careful not to encode extra metadata in this string\n * that should instead be placed in the Analytics Context or attributes.\n * Examples include:\n *\n * - view\n * - click\n * - filter\n * - search\n * - hover\n * - scroll\n */\n action: string;\n\n /**\n * A string that uniquely identifies the object that the action is being\n * taken on. Examples include:\n *\n * - The path of the page viewed\n * - The url of the link clicked\n * - The value that was filtered by\n * - The text that was searched for\n */\n subject: string;\n\n /**\n * An optional numeric value relevant to the event that could be aggregated\n * by analytics tools. Examples include:\n *\n * - The index or position of the clicked element in an ordered list\n * - The percentage of an element that has been scrolled through\n * - The amount of time that has elapsed since a fixed point\n * - A satisfaction score on a fixed scale\n */\n value?: number;\n\n /**\n * Optional, additional attributes (representing dimensions or metrics)\n * specific to the event that could be forwarded on to analytics systems.\n */\n attributes?: AnalyticsEventAttributes;\n\n /**\n * Contextual metadata relating to where the event was captured and by whom.\n * This could include information about the route, plugin, or extension in\n * which an event was captured.\n */\n context: AnalyticsContextValue;\n};\n\n/**\n * A structure allowing other arbitrary metadata to be provided by analytics\n * event emitters.\n *\n * @public\n */\nexport type AnalyticsEventAttributes = {\n [attribute in string]: string | boolean | number;\n};\n\n/**\n * Represents a tracker with methods that can be called to track events in a\n * configured analytics service.\n *\n * @public\n */\nexport type AnalyticsTracker = {\n captureEvent: (\n action: string,\n subject: string,\n options?: {\n value?: number;\n attributes?: AnalyticsEventAttributes;\n },\n ) => void;\n};\n\n/**\n * The Analytics API is used to track user behavior in a Backstage instance.\n *\n * @remarks\n *\n * To instrument your App or Plugin, retrieve an analytics tracker using the\n * useAnalytics() hook. This will return a pre-configured AnalyticsTracker\n * with relevant methods for instrumentation.\n *\n * @public\n */\nexport type AnalyticsApi = {\n /**\n * Primary event handler responsible for compiling and forwarding events to\n * an analytics system.\n */\n captureEvent(event: AnalyticsEvent): void;\n};\n\n/**\n * The {@link ApiRef} of {@link AnalyticsApi}.\n *\n * @public\n */\nexport const analyticsApiRef: ApiRef<AnalyticsApi> = createApiRef({\n id: 'core.analytics',\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 */\nimport { ApiRef, createApiRef } from '../system';\nimport { Config } from '@backstage/config';\n\n/**\n * The Config API is used to provide a mechanism to access the\n * runtime configuration of the system.\n *\n * @public\n */\nexport type ConfigApi = Config;\n\n/**\n * The {@link ApiRef} of {@link ConfigApi}.\n *\n * @public\n */\nexport const configApiRef: ApiRef<ConfigApi> = createApiRef({\n id: 'core.config',\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 */\nimport { ApiRef, createApiRef } from '../system';\n\n/**\n * The discovery API is used to provide a mechanism for plugins to\n * discover the endpoint to use to talk to their backend counterpart.\n *\n * @remarks\n *\n * The purpose of the discovery API is to allow for many different deployment\n * setups and routing methods through a central configuration, instead\n * of letting each individual plugin manage that configuration.\n *\n * Implementations of the discovery API can be a simple as a URL pattern\n * using the pluginId, but could also have overrides for individual plugins,\n * or query a separate discovery service.\n *\n * @public\n */\nexport type DiscoveryApi = {\n /**\n * Returns the HTTP base backend URL for a given plugin, without a trailing slash.\n *\n * This method must always be called just before making a request, as opposed to\n * fetching the URL when constructing an API client. That is to ensure that more\n * flexible routing patterns can be supported.\n *\n * For example, asking for the URL for `auth` may return something\n * like `https://backstage.example.com/api/auth`\n */\n getBaseUrl(pluginId: string): Promise<string>;\n};\n\n/**\n * The {@link ApiRef} of {@link DiscoveryApi}.\n *\n * @public\n */\nexport const discoveryApiRef: ApiRef<DiscoveryApi> = createApiRef({\n id: 'core.discovery',\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 { ApiRef, createApiRef } from '../system';\nimport { Observable } from '@backstage/types';\n\n/**\n * Mirrors the JavaScript Error class, for the purpose of\n * providing documentation and optional fields.\n *\n * @public\n */\nexport type ErrorApiError = {\n name: string;\n message: string;\n stack?: string;\n};\n\n/**\n * Provides additional information about an error that was posted to the application.\n *\n * @public\n */\nexport type ErrorApiErrorContext = {\n /**\n * If set to true, this error should not be displayed to the user.\n *\n * Hidden errors are typically not displayed in the UI, but the ErrorApi\n * implementation may still report them to error tracking services\n * or other utilities that care about all errors.\n *\n * @defaultValue false\n */\n hidden?: boolean;\n};\n\n/**\n * The error API is used to report errors to the app, and display them to the user.\n *\n * @remarks\n *\n * Plugins can use this API as a method of displaying errors to the user, but also\n * to report errors for collection by error reporting services.\n *\n * If an error can be displayed inline, e.g. as feedback in a form, that should be\n * preferred over relying on this API to display the error. The main use of this API\n * for displaying errors should be for asynchronous errors, such as a failing background process.\n *\n * Even if an error is displayed inline, it should still be reported through this API\n * if it would be useful to collect or log it for debugging purposes, but with\n * the hidden flag set. For example, an error arising from form field validation\n * should probably not be reported, while a failed REST call would be useful to report.\n *\n * @public\n */\nexport type ErrorApi = {\n /**\n * Post an error for handling by the application.\n */\n post(error: ErrorApiError, context?: ErrorApiErrorContext): void;\n\n /**\n * Observe errors posted by other parts of the application.\n */\n error$(): Observable<{\n error: ErrorApiError;\n context?: ErrorApiErrorContext;\n }>;\n};\n\n/**\n * The {@link ApiRef} of {@link ErrorApi}.\n *\n * @public\n */\nexport const errorApiRef: ApiRef<ErrorApi> = createApiRef({\n id: 'core.error',\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 { ApiRef, createApiRef } from '../system';\n\n/**\n * Feature flag descriptor.\n *\n * @public\n */\nexport type FeatureFlag = {\n name: string;\n pluginId: string;\n description?: string;\n};\n\n/**\n * Enum representing the state of a feature flag (inactive/active).\n *\n * @public\n */\nexport enum FeatureFlagState {\n /**\n * Feature flag inactive (disabled).\n */\n None = 0,\n /**\n * Feature flag active (enabled).\n */\n Active = 1,\n}\n\n/**\n * Options to use when saving feature flags.\n *\n * @public\n */\nexport type FeatureFlagsSaveOptions = {\n /**\n * The new feature flag states to save.\n */\n states: Record<string, FeatureFlagState>;\n\n /**\n * Whether the saves states should be merged into the existing ones, or replace them.\n *\n * Defaults to false.\n */\n merge?: boolean;\n};\n\n/**\n * The feature flags API is used to toggle functionality to users across plugins and Backstage.\n *\n * @remarks\n *\n * Plugins can use this API to register feature flags that they have available\n * for users to enable/disable, and this API will centralize the current user's\n * state of which feature flags they would like to enable.\n *\n * This is ideal for Backstage plugins, as well as your own App, to trial incomplete\n * or unstable upcoming features. Although there will be a common interface for users\n * to enable and disable feature flags, this API acts as another way to enable/disable.\n *\n * @public\n */\nexport interface FeatureFlagsApi {\n /**\n * Registers a new feature flag. Once a feature flag has been registered it\n * can be toggled by users, and read back to enable or disable features.\n */\n registerFlag(flag: FeatureFlag): void;\n\n /**\n * Get a list of all registered flags.\n */\n getRegisteredFlags(): FeatureFlag[];\n\n /**\n * Whether the feature flag with the given name is currently activated for the user.\n */\n isActive(name: string): boolean;\n\n /**\n * Save the user's choice of feature flag states.\n */\n save(options: FeatureFlagsSaveOptions): void;\n}\n\n/**\n * The {@link ApiRef} of {@link FeatureFlagsApi}.\n *\n * @public\n */\nexport const featureFlagsApiRef: ApiRef<FeatureFlagsApi> = createApiRef({\n id: 'core.featureflags',\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 { ApiRef, createApiRef } from '../system';\n\n/**\n * A wrapper for the fetch API, that has additional behaviors such as the\n * ability to automatically inject auth information where necessary.\n *\n * @public\n */\nexport type FetchApi = {\n /**\n * The `fetch` implementation.\n */\n fetch: typeof fetch;\n};\n\n/**\n * The {@link ApiRef} of {@link FetchApi}.\n *\n * @remarks\n *\n * This is a wrapper for the fetch API, that has additional behaviors such as\n * the ability to automatically inject auth information where necessary.\n *\n * Note that the default behavior of this API (unless overridden by your org),\n * is to require that the user is already signed in so that it has auth\n * information to inject. Therefore, using the default implementation of this\n * utility API e.g. on the `SignInPage` or similar, would cause issues. In\n * special circumstances like those, you can use the regular system `fetch`\n * instead.\n *\n * @public\n */\nexport const fetchApiRef: ApiRef<FetchApi> = createApiRef({\n id: 'core.fetch',\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 */\nimport { ApiRef, createApiRef } from '../system';\nimport { BackstageUserIdentity, ProfileInfo } from './auth';\n\n/**\n * The Identity API used to identify and get information about the signed in user.\n *\n * @public\n */\nexport type IdentityApi = {\n /**\n * The profile of the signed in user.\n */\n getProfileInfo(): Promise<ProfileInfo>;\n\n /**\n * User identity information within Backstage.\n */\n getBackstageIdentity(): Promise<BackstageUserIdentity>;\n\n /**\n * Provides credentials in the form of a token which proves the identity of the signed in user.\n *\n * The token will be undefined if the signed in user does not have a verified\n * identity, such as a demo user or mocked user for e2e tests.\n */\n getCredentials(): Promise<{ token?: string }>;\n\n /**\n * Sign out the current user\n */\n signOut(): Promise<void>;\n};\n\n/**\n * The {@link ApiRef} of {@link IdentityApi}.\n *\n * @public\n */\nexport const identityApiRef: ApiRef<IdentityApi> = createApiRef({\n id: 'core.identity',\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 { ApiRef, createApiRef } from '@backstage/core-plugin-api';\nimport { Expand, ExpandRecursive, Observable } from '@backstage/types';\nimport { TranslationRef } from '../../translation/TranslationRef';\nimport { JSX } from 'react';\n\n/**\n * Base translation options.\n *\n * @alpha\n */\ninterface BaseOptions {\n interpolation?: {\n /** Whether to HTML escape provided values, defaults to false */\n escapeValue?: boolean;\n };\n}\n\n/**\n * All pluralization suffixes supported by i18next\n *\n * @ignore\n */\ntype TranslationPlural = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other';\n\n/**\n * A mapping of i18n formatting types to their corresponding types and options.\n * @ignore\n */\ntype I18nextFormatMap = {\n number: {\n type: number;\n options: Intl.NumberFormatOptions;\n };\n currency: {\n type: number;\n options: Intl.NumberFormatOptions;\n };\n datetime: {\n type: Date;\n options: Intl.DateTimeFormatOptions;\n };\n relativetime: {\n type: number;\n options: {\n range?: Intl.RelativeTimeFormatUnit;\n } & Intl.RelativeTimeFormatOptions;\n };\n list: {\n type: string[];\n options: Intl.ListFormatOptions;\n };\n};\n\n/**\n * Extracts all pluralized keys from the message map.\n *\n * @example\n * ```\n * { foo: 'foo', bar_one: 'bar', bar_other: 'bars' } -> 'bar'\n * ```\n *\n * @ignore\n */\ntype PluralKeys<TMessages extends { [key in string]: string }> = {\n [Key in keyof TMessages]: Key extends `${infer K}_${TranslationPlural}`\n ? K\n : never;\n}[keyof TMessages];\n\n/**\n * Collapses a message map into normalized keys with union values.\n *\n * @example\n * ```\n * { foo_one: 'foo', foo_other: 'foos' } -> { foo: 'foo' | 'foos' }\n * ```\n *\n * @ignore\n */\ntype CollapsedMessages<TMessages extends { [key in string]: string }> = {\n [key in keyof TMessages as key extends `${infer K}_${TranslationPlural}`\n ? K\n : key]: TMessages[key];\n};\n\n/**\n * Trim away whitespace\n *\n * @ignore\n */\ntype Trim<T> = T extends ` ${infer U}`\n ? Trim<U>\n : T extends `${infer U} `\n ? Trim<U>\n : T;\n\n/**\n * Extracts the key and format from a replacement string.\n *\n * @example\n * ```\n * 'foo, number' -> { foo: number }, 'foo' -> { foo: undefined }\n * ```\n */\ntype ExtractFormat<Replacement extends string> =\n Replacement extends `${infer Key},${infer FullFormat}`\n ? {\n [key in Trim<Key>]: Lowercase<\n Trim<\n FullFormat extends `${infer Format}(${string})${string}`\n ? Format\n : FullFormat\n >\n >;\n }\n : { [key in Trim<Replacement>]: undefined };\n\n/**\n * Expand the keys in a flat map to nested objects.\n *\n * @example\n * ```\n * { 'a.b': 'foo', 'a.c': 'bar' } -> { a: { b: 'foo', c: 'bar' }\n * ```\n *\n * @ignore\n */\ntype ExpandKeys<TMap extends {}> = {\n [Key in keyof TMap as Key extends `${infer Prefix}.${string}`\n ? Prefix\n : Key]: Key extends `${string}.${infer Rest}`\n ? ExpandKeys<{ [key in Rest]: TMap[Key] }>\n : TMap[Key];\n};\n\n/**\n * Extracts all option keys and their format from a message string.\n *\n * @example\n * ```\n * 'foo {{bar}} {{baz, number}}' -> { 'bar': undefined, 'baz': 'number' }\n * ```\n *\n * @ignore\n */\ntype ReplaceFormatsFromMessage<TMessage> =\n TMessage extends `${string}{{${infer Replacement}}}${infer Tail}` // no formatting, e.g. {{foo}}\n ? ExpandKeys<ExtractFormat<Replacement>> & ReplaceFormatsFromMessage<Tail>\n : {};\n\n/**\n * Generates the replace options structure\n *\n * @ignore\n */\ntype ReplaceOptionsFromFormats<TFormats extends {}, TValueType> = {\n [Key in keyof TFormats]: TFormats[Key] extends keyof I18nextFormatMap\n ? I18nextFormatMap[TFormats[Key]]['type']\n : TFormats[Key] extends {}\n ? Expand<ReplaceOptionsFromFormats<TFormats[Key], TValueType>>\n : TValueType;\n};\n\n/**\n * Generates the formatParams options structure\n *\n * @ignore\n */\ntype ReplaceFormatParamsFromFormats<TFormats extends {}> = {\n [Key in keyof TFormats]?: TFormats[Key] extends keyof I18nextFormatMap\n ? I18nextFormatMap[TFormats[Key]]['options']\n : TFormats[Key] extends {}\n ? Expand<ReplaceFormatParamsFromFormats<TFormats[Key]>>\n : undefined;\n};\n\n/**\n * Extracts all nesting keys from a message string.\n *\n * @example\n * ```\n * 'foo $t(bar) $t(baz)' -> 'bar' | 'baz'\n * ```\n *\n * @ignore\n */\ntype NestingKeysFromMessage<TMessage extends string> =\n TMessage extends `${string}$t(${infer Key})${infer Tail}` // nesting options are not supported\n ? Trim<Key> | NestingKeysFromMessage<Tail>\n : never;\n\n/**\n * Find all referenced keys, given a starting key and the full set of messages.\n *\n * This will only discover keys up to 3 levels deep.\n *\n * @example\n * ```\n * <'x', { x: '$t(y) $t(z)', y: 'y', z: '$t(w)', w: 'w', foo: 'foo' }> -> 'x' | 'y' | 'z' | 'w'\n * ```\n *\n * @ignore\n */\ntype NestedMessageKeys<\n TKey extends keyof TMessages,\n TMessages extends { [key in string]: string },\n> =\n | TKey\n | NestedMessageKeys2<NestingKeysFromMessage<TMessages[TKey]>, TMessages>;\n// Can't recursively reference ourself, so instead we got this beauty\ntype NestedMessageKeys2<\n TKey extends keyof TMessages,\n TMessages extends { [key in string]: string },\n> =\n | TKey\n | NestedMessageKeys3<NestingKeysFromMessage<TMessages[TKey]>, TMessages>;\n// Only support 3 levels of nesting\ntype NestedMessageKeys3<\n TKey extends keyof TMessages,\n TMessages extends { [key in string]: string },\n> = TKey | NestingKeysFromMessage<TMessages[TKey]>;\n\n/**\n * Converts a union type to an intersection type.\n *\n * @example\n * ```\n * { foo: 'foo' } | { bar: 'bar' } -> { foo: 'foo' } & { bar: 'bar' }\n * ```\n *\n * @ignore\n */\ntype UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (\n k: infer I,\n) => void\n ? I\n : never;\n\n/**\n * Collects different types of options into a single object\n *\n * @ignore\n */\ntype CollectOptions<\n TCount extends { count?: number },\n TFormats extends {},\n TValueType,\n> = TCount &\n // count is special, omit it from the replacements\n (keyof Omit<TFormats, 'count'> extends never\n ? {}\n : (\n | Expand<Omit<ReplaceOptionsFromFormats<TFormats, TValueType>, 'count'>>\n | {\n replace: Expand<\n Omit<ReplaceOptionsFromFormats<TFormats, TValueType>, 'count'>\n >;\n }\n ) & {\n formatParams?: Expand<ReplaceFormatParamsFromFormats<TFormats>>;\n });\n\n/**\n * Helper type to only require options argument if needed\n *\n * @ignore\n */\ntype OptionArgs<TOptions extends {}> = keyof TOptions extends never\n ? [options?: Expand<BaseOptions>]\n : [options: Expand<BaseOptions & TOptions>];\n\n/**\n * @ignore\n */\ntype TranslationFunctionOptions<\n TKeys extends keyof TMessages, // All normalized message keys to be considered, i.e. included nested ones\n TPluralKeys extends keyof TMessages, // All keys in the message map that are pluralized\n TMessages extends { [key in string]: string }, // Collapsed message map with normalized keys and union values\n TValueType,\n> = OptionArgs<\n Expand<\n CollectOptions<\n TKeys & TPluralKeys extends never ? {} : { count: number },\n ExpandRecursive<\n UnionToIntersection<ReplaceFormatsFromMessage<TMessages[TKeys]>>\n >,\n TValueType\n >\n >\n>;\n\n/** @alpha */\nexport type TranslationFunction<TMessages extends { [key in string]: string }> =\n CollapsedMessages<TMessages> extends infer IMessages extends {\n [key in string]: string;\n }\n ? {\n /**\n * A translation function that returns a string.\n */\n <TKey extends keyof IMessages>(\n key: TKey,\n ...[args]: TranslationFunctionOptions<\n NestedMessageKeys<TKey, IMessages>,\n PluralKeys<TMessages>,\n IMessages,\n string\n >\n ): IMessages[TKey];\n /**\n * A translation function where at least one JSX.Element has been\n * provided as an interpolation value, and will therefore return a\n * JSX.Element.\n */\n <TKey extends keyof IMessages>(\n key: TKey,\n ...[args]: TranslationFunctionOptions<\n NestedMessageKeys<TKey, IMessages>,\n PluralKeys<TMessages>,\n IMessages,\n string | JSX.Element\n >\n ): JSX.Element;\n }\n : never;\n\n/** @alpha */\nexport type TranslationSnapshot<TMessages extends { [key in string]: string }> =\n { ready: false } | { ready: true; t: TranslationFunction<TMessages> };\n\n/** @alpha */\nexport type TranslationApi = {\n getTranslation<TMessages extends { [key in string]: string }>(\n translationRef: TranslationRef<string, TMessages>,\n ): TranslationSnapshot<TMessages>;\n\n translation$<TMessages extends { [key in string]: string }>(\n translationRef: TranslationRef<string, TMessages>,\n ): Observable<TranslationSnapshot<TMessages>>;\n};\n\n/**\n * @alpha\n */\nexport const translationApiRef: ApiRef<TranslationApi> = createApiRef({\n id: 'core.translation',\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 type { ApiRef } from './types';\n\n/**\n * API reference configuration - holds an ID of the referenced API.\n *\n * @public\n */\nexport type ApiRefConfig = {\n id: string;\n};\n\nclass ApiRefImpl<T> implements ApiRef<T> {\n constructor(private readonly config: ApiRefConfig) {\n const valid = config.id\n .split('.')\n .flatMap(part => part.split('-'))\n .every(part => part.match(/^[a-z][a-z0-9]*$/));\n if (!valid) {\n throw new Error(\n `API id must only contain period separated lowercase alphanum tokens with dashes, got '${config.id}'`,\n );\n }\n }\n\n get id(): string {\n return this.config.id;\n }\n\n // Utility for getting type of an api, using `typeof apiRef.T`\n get T(): T {\n throw new Error(`tried to read ApiRef.T of ${this}`);\n }\n\n toString() {\n return `apiRef{${this.config.id}}`;\n }\n}\n\n/**\n * Creates a reference to an API.\n *\n * @param config - The descriptor of the API to reference.\n * @returns An API reference.\n * @public\n */\nexport function createApiRef<T>(config: ApiRefConfig): ApiRef<T> {\n return new ApiRefImpl<T>(config);\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 { ApiRef, ApiFactory, TypesToApiRefs } from './types';\n\n/**\n * Used to infer types for a standalone {@link ApiFactory} that isn't immediately passed\n * to another function.\n *\n * @remarks\n *\n * This function doesn't actually do anything, it's only used to infer types.\n *\n * @public\n */\nexport function createApiFactory<\n Api,\n Impl extends Api,\n Deps extends { [name in string]: unknown },\n>(factory: ApiFactory<Api, Impl, Deps>): ApiFactory<Api, Impl, Deps>;\n/**\n * Used to infer types for a standalone {@link ApiFactory} that isn't immediately passed\n * to another function.\n *\n * @param api - Ref of the API that will be produced by the factory.\n * @param instance - Implementation of the API to use.\n * @public\n */\nexport function createApiFactory<Api, Impl extends Api>(\n api: ApiRef<Api>,\n instance: Impl,\n): ApiFactory<Api, Impl, {}>;\n/**\n * Used to infer types for a standalone {@link ApiFactory} that isn't immediately passed\n * to another function.\n *\n * @remarks\n *\n * Creates factory from {@link ApiRef} or returns the factory itself if provided.\n *\n * @param factory - Existing factory or {@link ApiRef}.\n * @param instance - The instance to be returned by the factory.\n * @public\n */\nexport function createApiFactory<\n Api,\n Impl extends Api,\n Deps extends { [name in string]: unknown },\n>(\n factory: ApiFactory<Api, Impl, Deps> | ApiRef<Api>,\n instance?: Impl,\n): ApiFactory<Api, Impl, Deps> {\n if ('id' in factory) {\n return {\n api: factory,\n deps: {} as TypesToApiRefs<Deps>,\n factory: () => instance!,\n };\n }\n return factory;\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 { ComponentType, PropsWithChildren } from 'react';\nimport { ApiRef, ApiHolder, TypesToApiRefs } from './types';\nimport { useVersionedContext } from '@backstage/version-bridge';\nimport { NotImplementedError } from '@backstage/errors';\n\n/**\n * React hook for retrieving {@link ApiHolder}, an API catalog.\n *\n * @public\n */\nexport function useApiHolder(): ApiHolder {\n const versionedHolder = useVersionedContext<{ 1: ApiHolder }>('api-context');\n if (!versionedHolder) {\n throw new NotImplementedError('API context is not available');\n }\n\n const apiHolder = versionedHolder.atVersion(1);\n if (!apiHolder) {\n throw new NotImplementedError('ApiContext v1 not available');\n }\n return apiHolder;\n}\n\n/**\n * React hook for retrieving APIs.\n *\n * @param apiRef - Reference of the API to use.\n * @public\n */\nexport function useApi<T>(apiRef: ApiRef<T>): T {\n const apiHolder = useApiHolder();\n\n const api = apiHolder.get(apiRef);\n if (!api) {\n throw new NotImplementedError(`No implementation available for ${apiRef}`);\n }\n return api;\n}\n\n/**\n * Wrapper for giving component an API context.\n *\n * @param apis - APIs for the context.\n * @public\n */\nexport function withApis<T extends {}>(apis: TypesToApiRefs<T>) {\n return function withApisWrapper<TProps extends T>(\n WrappedComponent: ComponentType<TProps>,\n ) {\n const Hoc = (props: PropsWithChildren<Omit<TProps, keyof T>>) => {\n const apiHolder = useApiHolder();\n\n const impls = {} as T;\n\n for (const key in apis) {\n if (apis.hasOwnProperty(key)) {\n const ref = apis[key];\n\n const api = apiHolder.get(ref);\n if (!api) {\n throw new NotImplementedError(\n `No implementation available for ${ref}`,\n );\n }\n impls[key] = api;\n }\n }\n\n return <WrappedComponent {...(props as TProps)} {...impls} />;\n };\n const displayName =\n WrappedComponent.displayName || WrappedComponent.name || 'Component';\n\n Hoc.displayName = `withApis(${displayName})`;\n\n return Hoc;\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 { useVersionedContext } from '@backstage/version-bridge';\nimport { AppContext as AppContextV1 } from './types';\n\n/**\n * React hook providing {@link AppContext}.\n *\n * @public\n */\nexport const useApp = (): AppContextV1 => {\n const versionedContext = useVersionedContext<{ 1: AppContextV1 }>(\n 'app-context',\n );\n if (!versionedContext) {\n throw new Error('App context is not available');\n }\n\n const appContext = versionedContext.atVersion(1);\n if (!appContext) {\n throw new Error('AppContext v1 not available');\n }\n return appContext;\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 { ComponentType, ReactNode } from 'react';\nimport { getOrCreateGlobalSingleton } from '@backstage/version-bridge';\n\ntype DataContainer = {\n map: Map<string, unknown>;\n};\n\n// This method of storing the component data was deprecated in September 2021, it\n// will be removed in the future for the reasons described below.\nconst globalStore = getOrCreateGlobalSingleton(\n 'component-data-store',\n () => new WeakMap<ComponentType<any>, DataContainer>(),\n);\n\n// This key is used to attach component data to the component type (function or class)\n// itself. This method is used because it has better compatibility component wrappers\n// like react-hot-loader, as opposed to the WeakMap method or using a symbol.\nconst componentDataKey = '__backstage_data';\n\ntype ComponentWithData = ComponentType<any> & {\n [componentDataKey]?: DataContainer;\n};\n\ntype MaybeComponentNode = ReactNode & {\n type?: ComponentWithData;\n};\n\n/**\n * Stores data related to a component in a global store.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#component-data}.\n *\n * @param component - The component to attach the data to.\n * @param type - The key under which the data will be stored.\n * @param data - Arbitrary value.\n * @public\n */\nexport function attachComponentData<P>(\n component: ComponentType<P>,\n type: string,\n data: unknown,\n) {\n const dataComponent = component as ComponentWithData;\n\n let container = dataComponent[componentDataKey] ?? globalStore.get(component);\n if (!container) {\n container = { map: new Map() };\n Object.defineProperty(dataComponent, componentDataKey, {\n enumerable: false,\n configurable: true,\n writable: false,\n value: container,\n });\n globalStore.set(component, container);\n }\n\n if (container.map.has(type)) {\n const name = component.displayName || component.name;\n throw new Error(\n `Attempted to attach duplicate data \"${type}\" to component \"${name}\"`,\n );\n }\n\n container.map.set(type, data);\n}\n\n/**\n * Retrieves data attached to a component.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#component-data}.\n *\n * @param node - React component to look up.\n * @param type - Key of the data to retrieve.\n * @returns Data stored using {@link attachComponentData}.\n * @public\n */\nexport function getComponentData<T>(\n node: ReactNode,\n type: string,\n): T | undefined {\n if (!node) {\n return undefined;\n }\n\n const component = (node as MaybeComponentNode).type;\n if (!component) {\n return undefined;\n }\n\n const container = component[componentDataKey] ?? globalStore.get(component);\n if (!container) {\n return undefined;\n }\n\n return container.map.get(type) as T | undefined;\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 { PropsWithChildren, Component } from 'react';\nimport { AppContext } from '../app/types';\nimport { BackstagePlugin } from '../plugin';\n\ntype Props = PropsWithChildren<{\n app: AppContext;\n plugin: BackstagePlugin;\n}>;\n\ntype State = { error: Error | undefined };\n\nexport class PluginErrorBoundary extends Component<Props, State> {\n static getDerivedStateFromError(error: Error) {\n return { error };\n }\n\n state: State = { error: undefined };\n\n handleErrorReset = () => {\n this.setState({ error: undefined });\n };\n\n render() {\n const { error } = this.state;\n const { app, plugin } = this.props;\n const { ErrorBoundaryFallback } = app.getComponents();\n\n if (error) {\n return (\n <ErrorBoundaryFallback\n error={error}\n resetError={this.handleErrorReset}\n plugin={plugin}\n />\n );\n }\n\n return this.props.children;\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 { lazy, Suspense, useEffect } from 'react';\nimport { AnalyticsContext, useAnalytics } from '../analytics';\nimport { useApp } from '../app';\nimport { RouteRef, useRouteRef } from '../routing';\nimport { attachComponentData } from './componentData';\nimport { Extension, BackstagePlugin } from '../plugin';\nimport { PluginErrorBoundary } from './PluginErrorBoundary';\nimport { routableExtensionRenderedEvent } from '../analytics/Tracker';\nimport { ForwardedError } from '@backstage/errors';\n\n/**\n * Lazy or synchronous retrieving of extension components.\n *\n * @public\n */\nexport type ComponentLoader<T> =\n | {\n lazy: () => Promise<T>;\n }\n | {\n sync: T;\n };\n\n/**\n * Extension for components that can have its own URL route (top-level pages, tabs etc.).\n *\n * @remarks\n *\n * We do not use ComponentType as the return type, since it doesn't let us convey the children prop.\n * ComponentType inserts children as an optional prop whether the inner component accepts it or not,\n * making it impossible to make the usage of children type safe.\n *\n * See {@link https://backstage.io/docs/plugins/composability#extensions}.\n *\n * @public\n */\nexport function createRoutableExtension<\n T extends (props: any) => JSX.Element | null,\n>(options: {\n /**\n * A loader for the component that is rendered by this extension.\n */\n component: () => Promise<T>;\n\n /**\n * The mount point to bind this routable extension to.\n *\n * If this extension is placed somewhere in the app element tree of a Backstage\n * app, callers will be able to route to this extensions by calling,\n * `useRouteRef` with this mount point.\n */\n mountPoint: RouteRef;\n\n /**\n * The name of this extension that will represent it at runtime. It is for example\n * used to identify this extension in analytics data.\n *\n * If possible the name should always be the same as the name of the exported\n * variable for this extension.\n */\n name?: string;\n}): Extension<T> {\n const { component, mountPoint, name } = options;\n return createReactExtension({\n component: {\n lazy: () =>\n component().then(InnerComponent => {\n const RoutableExtensionWrapper: any = (props: any) => {\n const analytics = useAnalytics();\n\n // Validate that the routing is wired up correctly in the App.tsx\n try {\n useRouteRef(mountPoint);\n } catch (error) {\n if (typeof error === 'object' && error !== null) {\n const { message } = error as { message?: unknown };\n if (\n typeof message === 'string' &&\n message.startsWith('No path for ')\n ) {\n throw new Error(\n `Routable extension component with mount point ${mountPoint} was not discovered in the app element tree. ` +\n 'Routable extension components may not be rendered by other components and must be ' +\n 'directly available as an element within the App provider component.',\n );\n }\n }\n throw error;\n }\n\n // This event, never exposed to end-users of the analytics API,\n // helps inform which extension metadata gets associated with a\n // navigation event when the route navigated to is a gathered\n // mountpoint.\n useEffect(() => {\n analytics.captureEvent(routableExtensionRenderedEvent, '');\n }, [analytics]);\n\n return <InnerComponent {...props} />;\n };\n\n const componentName =\n name ||\n (InnerComponent as { displayName?: string }).displayName ||\n InnerComponent.name ||\n 'LazyComponent';\n\n RoutableExtensionWrapper.displayName = `RoutableExtension(${componentName})`;\n\n return RoutableExtensionWrapper as T;\n }),\n },\n data: {\n 'core.mountPoint': mountPoint,\n },\n name,\n });\n}\n\n/**\n * Plain React component extension.\n *\n * @remarks\n *\n * We do not use ComponentType as the return type, since it doesn't let us convey the children prop.\n * ComponentType inserts children as an optional prop whether the inner component accepts it or not,\n * making it impossible to make the usage of children type safe.\n *\n * See {@link https://backstage.io/docs/plugins/composability#extensions}.\n *\n * @public\n */\nexport function createComponentExtension<\n T extends (props: any) => JSX.Element | null,\n>(options: {\n /**\n * A loader or synchronously supplied component that is rendered by this extension.\n */\n component: ComponentLoader<T>;\n\n /**\n * The name of this extension that will represent it at runtime. It is for example\n * used to identify this extension in analytics data.\n *\n * If possible the name should always be the same as the name of the exported\n * variable for this extension.\n */\n name?: string;\n}): Extension<T> {\n const { component, name } = options;\n return createReactExtension({ component, name });\n}\n\n/**\n * Used by {@link createComponentExtension} and {@link createRoutableExtension}.\n *\n * @remarks\n *\n * We do not use ComponentType as the return type, since it doesn't let us convey the children prop.\n * ComponentType inserts children as an optional prop whether the inner component accepts it or not,\n * making it impossible to make the usage of children type safe.\n *\n * See {@link https://backstage.io/docs/plugins/composability#extensions}.\n *\n * @public\n */\nexport function createReactExtension<\n T extends (props: any) => JSX.Element | null,\n>(options: {\n /**\n * A loader or synchronously supplied component that is rendered by this extension.\n */\n component: ComponentLoader<T>;\n\n /**\n * Additional component data that is attached to the top-level extension component.\n */\n data?: Record<string, unknown>;\n\n /**\n * The name of this extension that will represent it at runtime. It is for example\n * used to identify this extension in analytics data.\n *\n * If possible the name should always be the same as the name of the exported\n * variable for this extension.\n */\n name?: string;\n}): Extension<T> {\n const { data = {}, name } = options;\n if (!name) {\n // eslint-disable-next-line no-console\n console.warn(\n 'Declaring extensions without name is DEPRECATED. ' +\n 'Make sure that all usages of createReactExtension, createComponentExtension and createRoutableExtension provide a name.',\n );\n }\n\n let Component: T;\n if ('lazy' in options.component) {\n const lazyLoader = options.component.lazy;\n Component = lazy(() =>\n lazyLoader().then(\n component => ({ default: component }),\n error => {\n const ofExtension = name ? ` of the ${name} extension` : '';\n throw new ForwardedError(\n `Failed lazy loading${ofExtension}, try to reload the page`,\n error,\n );\n },\n ),\n ) as unknown as T;\n } else {\n Component = options.component.sync;\n }\n const componentName =\n name ||\n (Component as { displayName?: string }).displayName ||\n Component.name ||\n 'Component';\n\n return {\n expose(plugin: BackstagePlugin) {\n const Result: any = (props: any) => {\n const app = useApp();\n const { Progress } = app.getComponents();\n // todo(iamEAP): Account for situations where this is attached via\n // separate calls to attachComponentData().\n const mountPoint = data?.['core.mountPoint'] as\n | { id?: string }\n | undefined;\n\n return (\n <Suspense fallback={<Progress />}>\n <PluginErrorBoundary app={app} plugin={plugin}>\n <AnalyticsContext\n attributes={{\n pluginId: plugin.getId(),\n ...(name && { extension: name }),\n ...(mountPoint && { routeRef: mountPoint.id }),\n }}\n >\n <Component {...props} />\n </AnalyticsContext>\n </PluginErrorBoundary>\n </Suspense>\n );\n };\n\n attachComponentData(Result, 'core.plugin', plugin);\n attachComponentData(Result, 'core.extensionName', name);\n for (const [key, value] of Object.entries(data)) {\n attachComponentData(Result, key, value);\n }\n\n Result.displayName = `Extension(${componentName})`;\n return Result;\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 */\nimport {\n Children,\n Fragment,\n isValidElement,\n ReactNode,\n ReactElement,\n useMemo,\n} from 'react';\nimport { getComponentData } from './componentData';\nimport { useApi, FeatureFlagsApi, featureFlagsApiRef } from '../apis';\n\nfunction selectChildren(\n rootNode: ReactNode,\n featureFlagsApi: FeatureFlagsApi,\n selector?: (element: ReactElement<unknown>) => boolean,\n strictError?: string,\n): Array<ReactElement<unknown>> {\n return Children.toArray(rootNode).flatMap(node => {\n if (!isValidElement(node)) {\n return [];\n }\n\n if (node.type === Fragment) {\n return selectChildren(\n node.props.children,\n featureFlagsApi,\n selector,\n strictError,\n );\n }\n\n if (getComponentData(node, 'core.featureFlagged')) {\n const props = node.props as { with: string } | { without: string };\n const isEnabled =\n 'with' in props\n ? featureFlagsApi.isActive(props.with)\n : !featureFlagsApi.isActive(props.without);\n if (isEnabled) {\n return selectChildren(\n node.props.children,\n featureFlagsApi,\n selector,\n strictError,\n );\n }\n return [];\n }\n\n if (selector === undefined || selector(node)) {\n return [node];\n }\n\n if (strictError) {\n throw new Error(strictError);\n }\n\n return selectChildren(\n node.props.children,\n featureFlagsApi,\n selector,\n strictError,\n );\n });\n}\n\n/**\n * A querying interface tailored to traversing a set of selected React elements\n * and extracting data.\n *\n * @remarks\n *\n * Methods prefixed with `selectBy` are used to narrow the set of selected elements.\n *\n * Methods prefixed with `find` return concrete data using a deep traversal of the set.\n *\n * Methods prefixed with `get` return concrete data using a shallow traversal of the set.\n *\n * @public\n */\nexport interface ElementCollection {\n /**\n * Narrows the set of selected components by doing a deep traversal and\n * only including those that have defined component data for the given `key`.\n *\n * @remarks\n *\n * Whether an element in the tree has component data set for the given key\n * is determined by whether `getComponentData` returns undefined.\n *\n * The traversal does not continue deeper past elements that match the criteria,\n * and it also includes the root children in the selection, meaning that if the,\n * of all the currently selected elements contain data for the given key, this\n * method is a no-op.\n *\n * If `withStrictError` is set, the resulting selection must be a full match, meaning\n * there may be no elements that were excluded in the selection. If the selection\n * is not a clean match, an error will be throw with `withStrictError` as the message.\n *\n * @param query - Filtering query.\n */\n selectByComponentData(query: {\n key: string;\n withStrictError?: string;\n }): ElementCollection;\n\n /**\n * Finds all elements using the same criteria as `selectByComponentData`, but\n * returns the actual component data of each of those elements instead.\n *\n * @param query - Lookup query.\n */\n findComponentData<T>(query: { key: string }): T[];\n\n /**\n * Returns all of the elements currently selected by this collection.\n */\n getElements<Props extends { [name: string]: unknown }>(): Array<\n ReactElement<Props>\n >;\n}\n\nclass Collection implements ElementCollection {\n constructor(\n private readonly node: ReactNode,\n private readonly featureFlagsApi: FeatureFlagsApi,\n ) {}\n\n selectByComponentData(query: { key: string; withStrictError?: string }) {\n const selection = selectChildren(\n this.node,\n this.featureFlagsApi,\n node => getComponentData(node, query.key) !== undefined,\n query.withStrictError,\n );\n return new Collection(selection, this.featureFlagsApi);\n }\n\n findComponentData<T>(query: { key: string }): T[] {\n const selection = selectChildren(\n this.node,\n this.featureFlagsApi,\n node => getComponentData(node, query.key) !== undefined,\n );\n return selection\n .map(node => getComponentData<T>(node, query.key))\n .filter((data: T | undefined): data is T => data !== undefined);\n }\n\n getElements<Props extends { [name: string]: unknown }>(): Array<\n ReactElement<Props>\n > {\n return selectChildren(this.node, this.featureFlagsApi) as Array<\n ReactElement<Props>\n >;\n }\n}\n\n/**\n * useElementFilter is a utility that helps you narrow down and retrieve data\n * from a React element tree, typically operating on the `children` property\n * passed in to a component.\n *\n * @remarks\n *\n * A common use-case is to construct declarative APIs\n * where a React component defines its behavior based on its children, such as\n * the relationship between `Routes` and `Route` in `react-router`.\n *\n * The purpose of this hook is similar to `React.Children.map`, and it expands upon\n * it to also handle traversal of fragments and Backstage specific things like the\n * `FeatureFlagged` component.\n *\n * The return value of the hook is computed by the provided filter function, but\n * with added memoization based on the input `node`. If further memoization\n * dependencies are used in the filter function, they should be added to the\n * third `dependencies` argument, just like `useMemo`, `useEffect`, etc.\n *\n * @public\n */\nexport function useElementFilter<T>(\n node: ReactNode,\n filterFn: (arg: ElementCollection) => T,\n dependencies: any[] = [],\n) {\n const featureFlagsApi = useApi(featureFlagsApiRef);\n const elements = new Collection(node, featureFlagsApi);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => filterFn(elements), [node, ...dependencies]);\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 PluginConfig,\n BackstagePlugin,\n Extension,\n AnyRoutes,\n AnyExternalRoutes,\n PluginFeatureFlagConfig,\n} from './types';\nimport { AnyApiFactory } from '../apis';\n\n/**\n * @internal\n */\nexport class PluginImpl<\n Routes extends AnyRoutes,\n ExternalRoutes extends AnyExternalRoutes,\n> implements BackstagePlugin<Routes, ExternalRoutes>\n{\n constructor(private readonly config: PluginConfig<Routes, ExternalRoutes>) {}\n\n getId(): string {\n return this.config.id;\n }\n\n getApis(): Iterable<AnyApiFactory> {\n return this.config.apis ?? [];\n }\n\n getFeatureFlags(): Iterable<PluginFeatureFlagConfig> {\n return this.config.featureFlags?.slice() ?? [];\n }\n\n get routes(): Routes {\n return this.config.routes ?? ({} as Routes);\n }\n\n get externalRoutes(): ExternalRoutes {\n return this.config.externalRoutes ?? ({} as ExternalRoutes);\n }\n\n provide<T>(extension: Extension<T>): T {\n return extension.expose(this);\n }\n\n toString() {\n return `plugin{${this.config.id}}`;\n }\n}\n\n/**\n * Creates Backstage Plugin from config.\n *\n * @param config - Plugin configuration.\n * @public\n */\nexport function createPlugin<\n Routes extends AnyRoutes = {},\n ExternalRoutes extends AnyExternalRoutes = {},\n>(\n config: PluginConfig<Routes, ExternalRoutes>,\n): BackstagePlugin<Routes, ExternalRoutes> {\n return new PluginImpl(config);\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 RouteRef,\n routeRefType,\n AnyParams,\n ParamKeys,\n OptionalParams,\n} from './types';\n\n/**\n * @internal\n */\nexport class RouteRefImpl<Params extends AnyParams>\n implements RouteRef<Params>\n{\n // The marker is used for type checking while the symbol is used at runtime.\n declare $$routeRefType: 'absolute';\n readonly [routeRefType] = 'absolute';\n\n constructor(\n private readonly id: string,\n readonly params: ParamKeys<Params>,\n ) {}\n\n get title() {\n return this.id;\n }\n\n toString() {\n return `routeRef{type=absolute,id=${this.id}}`;\n }\n}\n\n/**\n * Create a {@link RouteRef} from a route descriptor.\n *\n * @param config - Description of the route reference to be created.\n * @public\n */\nexport function createRouteRef<\n // Params is the type that we care about and the one to be embedded in the route ref.\n // For example, given the params ['name', 'kind'], Params will be {name: string, kind: string}\n Params extends { [param in ParamKey]: string },\n // ParamKey is here to make sure the Params type properly has its keys narrowed down\n // to only the elements of params. Defaulting to never makes sure we end up with\n // Param = {} if the params array is empty.\n ParamKey extends string = never,\n>(config: {\n /** The id of the route ref, used to identify it when printed */\n id: string;\n /** A list of parameter names that the path that this route ref is bound to must contain */\n params?: ParamKey[];\n}): RouteRef<OptionalParams<Params>> {\n return new RouteRefImpl(\n config.id,\n (config.params ?? []) as ParamKeys<OptionalParams<Params>>,\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 { getOrCreateGlobalSingleton } from '@backstage/version-bridge';\n\n/**\n * Catch-all type for route params.\n *\n * @public\n */\nexport type AnyRouteRefParams = { [param in string]: string } | undefined;\n\n/**\n * @deprecated use {@link AnyRouteRefParams} instead\n * @public\n */\nexport type AnyParams = AnyRouteRefParams;\n\n/**\n * Type describing the key type of a route parameter mapping.\n *\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type ParamKeys<Params extends AnyParams> = [AnyRouteRefParams] extends [\n Params,\n]\n ? string[]\n : keyof Params extends never\n ? []\n : Array<keyof Params>;\n\n/**\n * Optional route params.\n *\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type OptionalParams<Params extends { [param in string]: string }> =\n Params[keyof Params] extends never ? undefined : Params;\n\n/**\n * TS magic for handling route parameters.\n *\n * @remarks\n *\n * The extra TS magic here is to require a single params argument if the RouteRef\n * had at least one param defined, but require 0 arguments if there are no params defined.\n * Without this we'd have to pass in empty object to all parameter-less RouteRefs\n * just to make TypeScript happy, or we would have to make the argument optional in\n * which case you might forget to pass it in when it is actually required.\n *\n * @public\n */\nexport type RouteFunc<Params extends AnyParams> = (\n ...[params]: Params extends undefined ? readonly [] : readonly [Params]\n) => string;\n\n/**\n * This symbol is what we use at runtime to determine whether a given object\n * is a type of RouteRef or not. It doesn't work well in TypeScript though since\n * the `unique symbol` will refer to different values between package versions.\n * For that reason we use the marker $$routeRefType to represent the symbol at\n * compile-time instead of using the symbol directly.\n *\n * @internal\n */\nexport const routeRefType: unique symbol = getOrCreateGlobalSingleton<any>(\n 'route-ref-type',\n () => Symbol('route-ref-type'),\n);\n\n/**\n * Absolute route reference.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport type RouteRef<Params extends AnyParams = any> = {\n /** @deprecated access to this property will be removed in the future */\n $$routeRefType: 'absolute'; // See routeRefType above\n\n /** @deprecated access to this property will be removed in the future */\n params: ParamKeys<Params>;\n};\n\n/**\n * Descriptor of a route relative to an absolute {@link RouteRef}.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport type SubRouteRef<Params extends AnyParams = any> = {\n /** @deprecated access to this property will be removed in the future */\n $$routeRefType: 'sub'; // See routeRefType above\n\n /** @deprecated access to this property will be removed in the future */\n parent: RouteRef;\n\n path: string;\n\n /** @deprecated access to this property will be removed in the future */\n params: ParamKeys<Params>;\n};\n\n/**\n * Route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport type ExternalRouteRef<\n Params extends AnyParams = any,\n Optional extends boolean = any,\n> = {\n /** @deprecated access to this property will be removed in the future */\n $$routeRefType: 'external'; // See routeRefType above\n\n /** @deprecated access to this property will be removed in the future */\n params: ParamKeys<Params>;\n\n optional?: Optional;\n};\n\n/**\n * @internal\n */\nexport type AnyRouteRef =\n | RouteRef<any>\n | SubRouteRef<any>\n | ExternalRouteRef<any, any>;\n\n/**\n * A duplicate of the react-router RouteObject, but with routeRef added\n * @internal\n */\nexport interface BackstageRouteObject {\n caseSensitive: boolean;\n children?: BackstageRouteObject[];\n element: React.ReactNode;\n path: string;\n routeRefs: Set<RouteRef>;\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 { useMemo } from 'react';\nimport { matchRoutes, useLocation } from 'react-router-dom';\nimport { useVersionedContext } from '@backstage/version-bridge';\nimport {\n AnyParams,\n ExternalRouteRef,\n RouteFunc,\n RouteRef,\n SubRouteRef,\n} from './types';\n\n/**\n * @internal\n */\nexport interface RouteResolver {\n resolve<Params extends AnyParams>(\n anyRouteRef:\n | RouteRef<Params>\n | SubRouteRef<Params>\n | ExternalRouteRef<Params, any>,\n sourceLocation: Parameters<typeof matchRoutes>[1],\n ): RouteFunc<Params> | undefined;\n}\n\n/**\n * React hook for constructing URLs to routes.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}\n *\n * @param routeRef - The ref to route that should be converted to URL.\n * @returns A function that will in turn return the concrete URL of the `routeRef`.\n * @public\n */\nexport function useRouteRef<Optional extends boolean, Params extends AnyParams>(\n routeRef: ExternalRouteRef<Params, Optional>,\n): Optional extends true ? RouteFunc<Params> | undefined : RouteFunc<Params>;\n\n/**\n * React hook for constructing URLs to routes.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}\n *\n * @param routeRef - The ref to route that should be converted to URL.\n * @returns A function that will in turn return the concrete URL of the `routeRef`.\n * @public\n */\nexport function useRouteRef<Params extends AnyParams>(\n routeRef: RouteRef<Params> | SubRouteRef<Params>,\n): RouteFunc<Params>;\n\n/**\n * React hook for constructing URLs to routes.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}\n *\n * @param routeRef - The ref to route that should be converted to URL.\n * @returns A function that will in turn return the concrete URL of the `routeRef`.\n * @public\n */\nexport function useRouteRef<Params extends AnyParams>(\n routeRef:\n | RouteRef<Params>\n | SubRouteRef<Params>\n | ExternalRouteRef<Params, any>,\n): RouteFunc<Params> | undefined {\n const { pathname } = useLocation();\n const versionedContext = useVersionedContext<{ 1: RouteResolver }>(\n 'routing-context',\n );\n if (!versionedContext) {\n throw new Error('Routing context is not available');\n }\n\n const resolver = versionedContext.atVersion(1);\n const routeFunc = useMemo(\n () => resolver && resolver.resolve(routeRef, { pathname }),\n [resolver, routeRef, pathname],\n );\n\n if (!versionedContext) {\n throw new Error('useRouteRef used outside of routing context');\n }\n if (!resolver) {\n throw new Error('RoutingContext v1 not available');\n }\n\n const isOptional = 'optional' in routeRef && routeRef.optional;\n if (!routeFunc && !isOptional) {\n throw new Error(`No path for ${routeRef}`);\n }\n\n return routeFunc;\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 {\n createTranslationResource,\n TranslationResource,\n} from './TranslationResource';\n\n/** @alpha */\nexport interface TranslationRef<\n TId extends string = string,\n TMessages extends { [key in string]: string } = { [key in string]: string },\n> {\n $$type: '@backstage/TranslationRef';\n\n id: TId;\n\n T: TMessages;\n}\n\n/** @internal */\ntype AnyMessages = { [key in string]: string };\n\n/** @ignore */\ntype AnyNestedMessages = { [key in string]: AnyNestedMessages | string };\n\n/**\n * Flattens a nested message declaration into a flat object with dot-separated keys.\n *\n * @ignore\n */\ntype FlattenedMessages<TMessages extends AnyNestedMessages> =\n // Flatten out object keys into a union structure of objects, e.g. { a: 'a', b: 'b' } -> { a: 'a' } | { b: 'b' }\n // Any nested object will be flattened into the individual unions, e.g. { a: 'a', b: { x: 'x', y: 'y' } } -> { a: 'a' } | { 'b.x': 'x', 'b.y': 'y' }\n // We create this structure by first nesting the desired union types into the original object, and\n // then extract them by indexing with `keyof TMessages` to form the union.\n // Throughout this the objects are wrapped up in a function parameter, which allows us to have the\n // final step of flipping this unions around to an intersection by inferring the function parameter.\n {\n [TKey in keyof TMessages]: (\n _: TMessages[TKey] extends infer TValue // \"local variable\" for the value\n ? TValue extends AnyNestedMessages\n ? FlattenedMessages<TValue> extends infer TNested // Recurse into nested messages, \"local variable\" for the result\n ? {\n [TNestedKey in keyof TNested as `${TKey & string}.${TNestedKey &\n string}`]: TNested[TNestedKey];\n }\n : never\n : { [_ in TKey]: TValue } // Primitive object values are passed through with the same key\n : never,\n ) => void;\n // The `[keyof TMessages]` extracts the object values union from our flattened structure, still wrapped up in function parameters.\n // The `extends (_: infer TIntersection) => void` flips the union to an intersection, at which point we have the correct type.\n }[keyof TMessages] extends (_: infer TIntersection) => void\n ? // This object mapping just expands similar to the Expand<> utility type, providing nicer type hints\n {\n readonly [TExpandKey in keyof TIntersection]: TIntersection[TExpandKey];\n }\n : never;\n\n/** @internal */\nexport interface InternalTranslationRef<\n TId extends string = string,\n TMessages extends { [key in string]: string } = { [key in string]: string },\n> extends TranslationRef<TId, TMessages> {\n version: 'v1';\n\n getDefaultMessages(): AnyMessages;\n\n getDefaultResource(): TranslationResource | undefined;\n}\n\n/** @alpha */\nexport interface TranslationRefOptions<\n TId extends string,\n TNestedMessages extends AnyNestedMessages,\n TTranslations extends {\n [language in string]: () => Promise<{\n default: {\n [key in keyof FlattenedMessages<TNestedMessages>]: string | null;\n };\n }>;\n },\n> {\n id: TId;\n messages: TNestedMessages;\n translations?: TTranslations;\n}\n\nfunction flattenMessages(nested: AnyNestedMessages): AnyMessages {\n const entries = new Array<[string, string]>();\n\n function visit(obj: AnyNestedMessages, prefix: string): void {\n for (const [key, value] of Object.entries(obj)) {\n if (typeof value === 'string') {\n entries.push([prefix + key, value]);\n } else {\n visit(value, `${prefix}${key}.`);\n }\n }\n }\n\n visit(nested, '');\n\n return Object.fromEntries(entries);\n}\n\n/** @internal */\nclass TranslationRefImpl<\n TId extends string,\n TNestedMessages extends AnyNestedMessages,\n> implements InternalTranslationRef<TId, FlattenedMessages<TNestedMessages>>\n{\n #id: TId;\n #messages: FlattenedMessages<TNestedMessages>;\n #resources: TranslationResource | undefined;\n\n constructor(options: TranslationRefOptions<TId, TNestedMessages, any>) {\n this.#id = options.id;\n this.#messages = flattenMessages(\n options.messages,\n ) as FlattenedMessages<TNestedMessages>;\n }\n\n $$type = '@backstage/TranslationRef' as const;\n\n version = 'v1' as const;\n\n get id(): TId {\n return this.#id;\n }\n\n get T(): never {\n throw new Error('Not implemented');\n }\n\n getDefaultMessages(): AnyMessages {\n return this.#messages;\n }\n\n setDefaultResource(resources: TranslationResource): void {\n this.#resources = resources;\n }\n\n getDefaultResource(): TranslationResource | undefined {\n return this.#resources;\n }\n\n toString() {\n return `TranslationRef{id=${this.id}}`;\n }\n}\n\n/** @alpha */\nexport function createTranslationRef<\n TId extends string,\n const TNestedMessages extends AnyNestedMessages,\n TTranslations extends {\n [language in string]: () => Promise<{\n default: {\n [key in keyof FlattenedMessages<TNestedMessages>]: string | null;\n };\n }>;\n },\n>(\n config: TranslationRefOptions<TId, TNestedMessages, TTranslations>,\n): TranslationRef<TId, FlattenedMessages<TNestedMessages>> {\n const ref = new TranslationRefImpl(config);\n if (config.translations) {\n ref.setDefaultResource(\n createTranslationResource({\n ref,\n translations: config.translations as any,\n }),\n );\n }\n return ref;\n}\n\n/** @internal */\nexport function toInternalTranslationRef<\n TId extends string,\n TMessages extends AnyMessages,\n>(ref: TranslationRef<TId, TMessages>): InternalTranslationRef<TId, TMessages> {\n const r = ref as InternalTranslationRef<TId, TMessages>;\n if (r.$$type !== '@backstage/TranslationRef') {\n throw new Error(`Invalid translation ref, bad type '${r.$$type}'`);\n }\n if (r.version !== 'v1') {\n throw new Error(`Invalid translation ref, bad version '${r.version}'`);\n }\n return r;\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 {\n TranslationMessages,\n TranslationRef,\n} from '@backstage/core-plugin-api/alpha';\n\n/** @alpha */\nexport interface TranslationResource<TId extends string = string> {\n $$type: '@backstage/TranslationResource';\n id: TId;\n}\n\n/** @internal */\nexport type InternalTranslationResourceLoader = () => Promise<{\n messages: { [key in string]: string | null };\n}>;\n\n/** @internal */\nexport interface InternalTranslationResource<TId extends string = string>\n extends TranslationResource<TId> {\n version: 'v1';\n resources: Array<{\n language: string;\n loader: InternalTranslationResourceLoader;\n }>;\n}\n\n/** @internal */\nexport function toInternalTranslationResource<TId extends string>(\n resource: TranslationResource<TId>,\n): InternalTranslationResource<TId> {\n const r = resource as InternalTranslationResource<TId>;\n if (r.$$type !== '@backstage/TranslationResource') {\n throw new Error(`Invalid translation resource, bad type '${r.$$type}'`);\n }\n if (r.version !== 'v1') {\n throw new Error(`Invalid translation resource, bad version '${r.version}'`);\n }\n\n return r;\n}\n\n/** @alpha */\nexport interface TranslationResourceOptions<\n TId extends string,\n TMessages extends { [key in string]: string },\n TTranslations extends {\n [language in string]: () => Promise<{\n default:\n | TranslationMessages<TId>\n | { [key in keyof TMessages]: string | null };\n }>;\n },\n> {\n ref: TranslationRef<TId, TMessages>;\n\n translations: TTranslations;\n}\n\n/** @alpha */\nexport function createTranslationResource<\n TId extends string,\n TMessages extends { [key in string]: string },\n TTranslations extends {\n [language in string]: () => Promise<{\n default:\n | TranslationMessages<TId>\n | { [key in keyof TMessages]: string | null };\n }>;\n },\n>(\n options: TranslationResourceOptions<TId, TMessages, TTranslations>,\n): TranslationResource<TId> {\n return {\n $$type: '@backstage/TranslationResource',\n version: 'v1',\n id: options.ref.id,\n resources: Object.entries(options.translations).map(\n ([language, loader]) => ({\n language,\n loader: () =>\n loader().then(m => {\n const value = m.default;\n return {\n messages:\n value?.$$type === '@backstage/TranslationMessages'\n ? value.messages\n : value,\n };\n }),\n }),\n ),\n } as InternalTranslationResource<TId>;\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 { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { errorApiRef, useApi } from '../apis';\nimport {\n translationApiRef,\n TranslationFunction,\n TranslationSnapshot,\n} from '../apis/alpha';\nimport { TranslationRef } from './TranslationRef';\n\n// Make sure we don't fill the logs with loading errors for the same ref\nconst loggedRefs = new WeakSet<TranslationRef<string, {}>>();\n\n/** @alpha */\nexport const useTranslationRef = <\n TMessages extends { [key in string]: string },\n>(\n translationRef: TranslationRef<string, TMessages>,\n): { t: TranslationFunction<TMessages> } => {\n const errorApi = useApi(errorApiRef);\n const translationApi = useApi(translationApiRef);\n\n const [snapshot, setSnapshot] = useState<TranslationSnapshot<TMessages>>(() =>\n translationApi.getTranslation(translationRef),\n );\n const observable = useMemo(\n () => translationApi.translation$(translationRef),\n [translationApi, translationRef],\n );\n\n const onError = useCallback(\n (error: Error) => {\n if (!loggedRefs.has(translationRef)) {\n const errMsg = `Failed to load translation resource '${translationRef.id}'; caused by ${error}`;\n // eslint-disable-next-line no-console\n console.error(errMsg);\n errorApi.post(new Error(errMsg));\n loggedRefs.add(translationRef);\n }\n },\n [errorApi, translationRef],\n );\n\n useEffect(() => {\n const subscription = observable.subscribe({\n next(next) {\n if (next.ready) {\n setSnapshot(next);\n }\n },\n error(error) {\n onError(error);\n },\n });\n\n return () => {\n subscription.unsubscribe();\n };\n }, [observable, onError]);\n\n // Keep track of if the provided translation ref changes, and in that case update the snapshot\n const initialRenderRef = useRef(true);\n useEffect(() => {\n if (initialRenderRef.current) {\n initialRenderRef.current = false;\n } else {\n setSnapshot(translationApi.getTranslation(translationRef));\n }\n }, [translationApi, translationRef]);\n\n if (!snapshot.ready) {\n throw new Promise<void>(resolve => {\n const subscription = observable.subscribe({\n next(next) {\n if (next.ready) {\n subscription.unsubscribe();\n resolve();\n }\n },\n error(error) {\n subscription.unsubscribe();\n onError(error);\n resolve();\n },\n });\n });\n }\n\n return { t: snapshot.t };\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 { ConsumedResponse } from '../errors/types';\nimport { SerializedError } from './error';\n\n/**\n * A standard shape of JSON data returned as the body of backend errors.\n *\n * @public\n */\nexport type ErrorResponseBody = {\n /** Details of the error that was caught */\n error: SerializedError;\n\n /** Details about the incoming request */\n request?: {\n /** The HTTP method of the request */\n method: string;\n /** The URL of the request (excluding protocol and host/port) */\n url: string;\n };\n\n /** Details about the response */\n response: {\n /** The numeric HTTP status code that was returned */\n statusCode: number;\n };\n};\n\n/**\n * Attempts to construct an ErrorResponseBody out of a failed server request.\n * Assumes that the response has already been checked to be not ok. This\n * function consumes the body of the response, and assumes that it hasn't\n * been consumed before.\n *\n * The code is forgiving, and constructs a useful synthetic body as best it can\n * if the response body wasn't on the expected form.\n *\n * @public\n * @param response - The response of a failed request\n */\nexport async function parseErrorResponseBody(\n response: ConsumedResponse & { text(): Promise<string> },\n): Promise<ErrorResponseBody> {\n try {\n const text = await response.text();\n if (text) {\n if (\n response.headers.get('content-type')?.startsWith('application/json')\n ) {\n try {\n const body = JSON.parse(text);\n if (body.error && body.response) {\n return body;\n }\n } catch {\n // ignore\n }\n }\n\n return {\n error: {\n name: 'Error',\n message: `Request failed with status ${response.status} ${response.statusText}, ${text}`,\n },\n response: {\n statusCode: response.status,\n },\n };\n }\n } catch {\n // ignore\n }\n\n return {\n error: {\n name: 'Error',\n message: `Request failed with status ${response.status} ${response.statusText}`,\n },\n response: {\n statusCode: response.status,\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 { deserializeError } from '../serialization/error';\nimport {\n ErrorResponseBody,\n parseErrorResponseBody,\n} from '../serialization/response';\nimport { ConsumedResponse } from './types';\n\n/**\n * An error thrown as the result of a failed server request.\n *\n * The server is expected to respond on the ErrorResponseBody format.\n *\n * @public\n */\nexport class ResponseError extends Error {\n /**\n * The actual response, as seen by the client.\n *\n * Note that the body of this response is always consumed. Its parsed form is\n * in the `body` field.\n */\n readonly response: ConsumedResponse;\n\n /**\n * The parsed JSON error body, as sent by the server.\n */\n readonly body: ErrorResponseBody;\n\n /**\n * The Error cause, as seen by the remote server. This is parsed out of the\n * JSON error body.\n *\n * This error always has the plain Error constructor, however all\n * serializable enumerable fields on the remote error including its name are\n * preserved. Therefore, if you want to check the error type, use its name\n * property rather than checking typeof or its constructor or prototype.\n */\n readonly cause: Error;\n\n readonly statusCode: number;\n\n readonly statusText: string;\n /**\n * Constructs a ResponseError based on a failed response.\n *\n * Assumes that the response has already been checked to be not ok. This\n * function consumes the body of the response, and assumes that it hasn't\n * been consumed before.\n */\n static async fromResponse(\n response: ConsumedResponse & { text(): Promise<string> },\n ): Promise<ResponseError> {\n const data = await parseErrorResponseBody(response);\n\n const statusCode = data.response.statusCode || response.status;\n const statusText = response.statusText;\n const message = `Request failed with ${statusCode} ${statusText}`;\n const cause = deserializeError(data.error);\n\n return new ResponseError({\n message,\n response,\n data,\n cause,\n statusCode,\n statusText,\n });\n }\n\n private constructor(opts: {\n message: string;\n response: ConsumedResponse;\n data: ErrorResponseBody;\n cause: Error;\n statusCode: number;\n statusText: string;\n }) {\n super(opts.message);\n\n this.name = 'ResponseError';\n this.response = opts.response;\n this.body = opts.data;\n this.cause = opts.cause;\n this.statusCode = opts.statusCode;\n this.statusText = opts.statusText;\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\n/**\n * An object that is shaped like an `Error`.\n *\n * @public\n */\nexport type ErrorLike = {\n name: string;\n message: string;\n stack?: string;\n [unknownKeys: string]: unknown;\n};\n\n/**\n * Checks whether an unknown value is an {@link ErrorLike} object, which guarantees that it's\n * an object that has at least two string properties: a non-empty `name` and `message`.\n *\n * @public\n * @param value - an unknown value\n * @returns true if the value is an {@link ErrorLike} object, false otherwise\n */\nexport function isError(value: unknown): value is ErrorLike {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n const maybe = value as Partial<ErrorLike>;\n if (typeof maybe.name !== 'string' || maybe.name === '') {\n return false;\n }\n if (typeof maybe.message !== 'string') {\n return false;\n }\n return true;\n}\n\n/**\n * Asserts that an unknown value is an {@link ErrorLike} object, which guarantees that it's\n * an object that has at least two string properties: a non-empty `name` and `message`.\n *\n * If the value is not an {@link ErrorLike} object, an error is thrown.\n *\n * @public\n * @param value - an unknown value\n */\nexport function assertError(value: unknown): asserts value is ErrorLike {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new Error(`Encountered invalid error, not an object, got '${value}'`);\n }\n const maybe = value as Partial<ErrorLike>;\n if (typeof maybe.name !== 'string' || maybe.name === '') {\n throw new Error(`Encountered error object without a name, got '${value}'`);\n }\n if (typeof maybe.message !== 'string') {\n throw new Error(\n `Encountered error object without a message, got '${value}'`,\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 { stringifyError } from '../serialization/error';\nimport { isError } from './assertion';\n\n/**\n * A base class that custom Error classes can inherit from.\n *\n * @public\n * @example\n *\n * ```ts\n * class MyCustomError extends CustomErrorBase {\n * name = 'MyCustomError' as const;\n * }\n *\n * const e = new MyCustomError('Some message', cause);\n * // e.name === 'MyCustomError'\n * // e.message === 'Some message'\n * // e.cause === cause\n * // e.stack is set if the runtime supports it\n * ```\n */\nexport class CustomErrorBase extends Error {\n /**\n * An inner error that caused this error to be thrown, if any.\n */\n readonly cause?: Error | undefined;\n\n constructor(message?: string, cause?: Error | unknown) {\n let fullMessage = message;\n if (cause !== undefined) {\n const causeStr = stringifyError(cause);\n if (fullMessage) {\n fullMessage += `; caused by ${causeStr}`;\n } else {\n fullMessage = `caused by ${causeStr}`;\n }\n }\n\n super(fullMessage);\n\n Error.captureStackTrace?.(this, this.constructor);\n\n if (!this.name || this.name === 'Error') {\n const baseName = this.constructor.name;\n if (baseName !== 'Error') {\n this.name = this.constructor.name;\n }\n }\n\n this.cause = isError(cause) ? cause : undefined;\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 { isError } from './assertion';\nimport { CustomErrorBase } from './CustomErrorBase';\n\n/*\n * A set of common business logic errors.\n *\n * A backend error handler middleware would understand these and translate them\n * to well formed HTTP responses.\n *\n * While these are intentionally analogous to HTTP errors, they are not\n * intended to be thrown by the request handling layer. In those places, please\n * use e.g. the http-errors library.\n */\n\n/**\n * The given inputs are malformed and cannot be processed.\n *\n * @public\n */\nexport class InputError extends CustomErrorBase {\n name = 'InputError' as const;\n}\n\n/**\n * The request requires authentication, which was not properly supplied.\n *\n * @public\n */\nexport class AuthenticationError extends CustomErrorBase {\n name = 'AuthenticationError' as const;\n}\n\n/**\n * The authenticated caller is not allowed to perform this request.\n *\n * @public\n */\nexport class NotAllowedError extends CustomErrorBase {\n name = 'NotAllowedError' as const;\n}\n\n/**\n * The requested resource could not be found.\n *\n * Note that this error usually is used to indicate that an entity with a given\n * ID does not exist, rather than signalling that an entire route is missing.\n *\n * @public\n */\nexport class NotFoundError extends CustomErrorBase {\n name = 'NotFoundError' as const;\n}\n\n/**\n * The request could not complete due to a conflict in the current state of the\n * resource.\n *\n * @public\n */\nexport class ConflictError extends CustomErrorBase {\n name = 'ConflictError' as const;\n}\n\n/**\n * The requested resource has not changed since last request.\n *\n * @public\n */\nexport class NotModifiedError extends CustomErrorBase {\n name = 'NotModifiedError' as const;\n}\n\n/**\n * The server does not support the functionality required to fulfill the request.\n *\n * @public\n */\nexport class NotImplementedError extends CustomErrorBase {\n name = 'NotImplementedError' as const;\n}\n\n/**\n * The server is not ready to handle the request.\n *\n * @public\n */\nexport class ServiceUnavailableError extends CustomErrorBase {}\n\n/**\n * An error that forwards an underlying cause with additional context in the message.\n *\n * The `name` property of the error will be inherited from the `cause` if\n * possible, and will otherwise be set to `'Error'`.\n *\n * @public\n */\nexport class ForwardedError extends CustomErrorBase {\n constructor(message: string, cause: Error | unknown) {\n super(message, cause);\n\n this.name = isError(cause) ? cause.name : 'Error';\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 { JsonObject } from '@backstage/types';\nimport {\n deserializeError as deserializeErrorInternal,\n serializeError as serializeErrorInternal,\n} from 'serialize-error';\nimport { isError } from '../errors/assertion';\n\n/**\n * The serialized form of an Error.\n *\n * @public\n */\nexport type SerializedError = JsonObject & {\n /** The name of the exception that was thrown */\n name: string;\n /** The message of the exception that was thrown */\n message: string;\n /** A stringified stack trace; may not be present */\n stack?: string;\n /** A custom code (not necessarily the same as an HTTP response code); may not be present */\n code?: string;\n};\n\n/**\n * Serializes an error object to a JSON friendly form.\n *\n * @public\n * @param error - The error.\n * @param options - Optional serialization options.\n */\nexport function serializeError(\n error: Error,\n options?: {\n /** Include stack trace in the output (default false) */\n includeStack?: boolean;\n },\n): SerializedError {\n const serialized = serializeErrorInternal(error);\n const result: SerializedError = {\n name: 'Unknown',\n message: '<no reason given>',\n ...serialized,\n };\n\n if (!options?.includeStack) {\n delete result.stack;\n\n if (\n result.cause &&\n typeof result.cause === 'object' &&\n 'stack' in result.cause\n ) {\n delete result.cause.stack;\n }\n }\n\n return result;\n}\n\n/**\n * Deserializes a serialized error object back to an Error.\n *\n * @public\n */\nexport function deserializeError<T extends Error = Error>(\n data: SerializedError,\n): T {\n const result = deserializeErrorInternal(data) as T;\n if (!data.stack) {\n result.stack = undefined;\n }\n return result;\n}\n\n/**\n * Stringifies an error, including its name and message where available.\n *\n * @param error - The error.\n * @public\n */\nexport function stringifyError(error: unknown): string {\n if (isError(error)) {\n // Prefer error.toString, but if it's not implemented we use a nicer fallback\n const str = String(error);\n return str !== '[object Object]' ? str : `${error.name}: ${error.message}`;\n }\n\n return `unknown error '${error}'`;\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 { Config } from '@backstage/config';\n\nconst AMAZON_AWS_HOST = 'amazonaws.com';\n\n/**\n * The configuration parameters for a single AWS S3 provider.\n *\n * @public\n */\nexport type AwsS3IntegrationConfig = {\n /**\n * Host, derived from endpoint, and defaults to amazonaws.com\n */\n host: string;\n\n /**\n * (Optional) AWS Endpoint.\n * The endpoint URI to send requests to. The default endpoint is built from the configured region.\n * @see https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property\n *\n * Supports non-AWS providers, e.g. for LocalStack, endpoint may look like http://localhost:4566\n */\n endpoint?: string;\n\n /**\n * (Optional) Whether to use path style URLs when communicating with S3.\n * Defaults to false.\n * This allows providers like LocalStack, Minio and Wasabi (and possibly others) to be used.\n */\n s3ForcePathStyle?: boolean;\n\n /**\n * (Optional) User access key id\n */\n accessKeyId?: string;\n\n /**\n * (Optional) User secret access key\n */\n secretAccessKey?: string;\n\n /**\n * (Optional) ARN of role to be assumed\n */\n roleArn?: string;\n\n /**\n * (Optional) External ID to use when assuming role\n */\n externalId?: string;\n};\n\n/**\n * Reads a single Aws S3 integration config.\n *\n * @param config - The config object of a single integration\n * @public\n */\n\nexport function readAwsS3IntegrationConfig(\n config: Config,\n): AwsS3IntegrationConfig {\n const endpoint = config.getOptionalString('endpoint');\n const s3ForcePathStyle =\n config.getOptionalBoolean('s3ForcePathStyle') ?? false;\n let host;\n let pathname;\n if (endpoint) {\n try {\n const url = new URL(endpoint);\n host = url.host;\n pathname = url.pathname;\n } catch {\n throw new Error(\n `invalid awsS3 integration config, endpoint '${endpoint}' is not a valid URL`,\n );\n }\n if (pathname !== '/') {\n throw new Error(\n `invalid awsS3 integration config, endpoints cannot contain path, got '${endpoint}'`,\n );\n }\n } else {\n host = AMAZON_AWS_HOST;\n }\n\n const accessKeyId = config.getOptionalString('accessKeyId');\n const secretAccessKey = config.getOptionalString('secretAccessKey')?.trim();\n const roleArn = config.getOptionalString('roleArn');\n const externalId = config.getOptionalString('externalId');\n\n return {\n host,\n endpoint,\n s3ForcePathStyle,\n accessKeyId,\n secretAccessKey,\n roleArn,\n externalId,\n };\n}\n\n/**\n * Reads a set of AWS S3 integration configs, and inserts some defaults for\n * public Amazon AWS if not specified.\n *\n * @param configs - The config objects of the integrations\n * @public\n */\nexport function readAwsS3IntegrationConfigs(\n configs: Config[],\n): AwsS3IntegrationConfig[] {\n // First read all the explicit integrations\n const result = configs.map(readAwsS3IntegrationConfig);\n\n // If no explicit amazonaws.com integration was added, put one in the list as\n // a convenience\n if (!result.some(c => c.host === AMAZON_AWS_HOST)) {\n result.push({\n host: AMAZON_AWS_HOST,\n });\n }\n return result;\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 { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport { AwsS3IntegrationConfig, readAwsS3IntegrationConfigs } from './config';\n\n/**\n * Integrates with AWS S3 or compatible solutions.\n *\n * @public\n */\nexport class AwsS3Integration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<AwsS3Integration> = ({ config }) => {\n const configs = readAwsS3IntegrationConfigs(\n config.getOptionalConfigArray('integrations.awsS3') ?? [],\n );\n return basicIntegrations(\n configs.map(c => new AwsS3Integration(c)),\n i => i.config.host,\n );\n };\n\n get type(): string {\n return 'awsS3';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): AwsS3IntegrationConfig {\n return this.integrationConfig;\n }\n\n constructor(private readonly integrationConfig: AwsS3IntegrationConfig) {}\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number | undefined;\n }): string {\n const resolved = defaultScmResolveUrl(options);\n return resolved;\n }\n\n resolveEditUrl(url: string): string {\n // TODO: Implement edit URL for awsS3\n return url;\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 { Config } from '@backstage/config';\n\nconst AMAZON_AWS_CODECOMMIT_HOST = 'console.aws.amazon.com';\n\n/**\n * The configuration parameters for a single AWS CodeCommit provider.\n *\n * @public\n */\nexport type AwsCodeCommitIntegrationConfig = {\n /**\n * Host, git host derived from region\n */\n host: string;\n\n /**\n * (Optional) User access key id\n */\n accessKeyId?: string;\n\n /**\n * (Optional) User secret access key\n */\n secretAccessKey?: string;\n\n /**\n * (Optional) ARN of role to be assumed\n */\n roleArn?: string;\n\n /**\n * (Optional) External ID to use when assuming role\n */\n externalId?: string;\n\n /**\n * region to use for AWS (default: us-east-1)\n */\n region: string;\n};\n\n/**\n * Reads a single Aws CodeCommit integration config.\n *\n * @param config - The config object of a single integration\n * @public\n */\n\nexport function readAwsCodeCommitIntegrationConfig(\n config: Config,\n): AwsCodeCommitIntegrationConfig {\n const accessKeyId = config.getOptionalString('accessKeyId');\n const secretAccessKey = config.getOptionalString('secretAccessKey')?.trim();\n const roleArn = config.getOptionalString('roleArn');\n const externalId = config.getOptionalString('externalId');\n const region = config.getString('region');\n const host =\n config.getOptionalString('host') ||\n `${region}.${AMAZON_AWS_CODECOMMIT_HOST}`;\n\n return {\n host,\n accessKeyId,\n secretAccessKey,\n roleArn,\n externalId,\n region,\n };\n}\n\n/**\n * Reads a set of AWS CodeCommit integration configs, and inserts some defaults for\n * public Amazon AWS if not specified.\n *\n * @param configs - The config objects of the integrations\n * @public\n */\nexport function readAwsCodeCommitIntegrationConfigs(\n configs: Config[],\n): AwsCodeCommitIntegrationConfig[] {\n return configs.map(readAwsCodeCommitIntegrationConfig);\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 { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport {\n AwsCodeCommitIntegrationConfig,\n readAwsCodeCommitIntegrationConfigs,\n} from './config';\n\n/**\n * Integrates with AWS CodeCommit.\n *\n * @public\n */\nexport class AwsCodeCommitIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<AwsCodeCommitIntegration> = ({\n config,\n }) => {\n const configs = readAwsCodeCommitIntegrationConfigs(\n config.getOptionalConfigArray('integrations.awsCodeCommit') ?? [],\n );\n return basicIntegrations(\n configs.map(c => new AwsCodeCommitIntegration(c)),\n i => i.config.host,\n );\n };\n\n get type(): string {\n return 'awsCodeCommit';\n }\n\n get config(): AwsCodeCommitIntegrationConfig {\n return this.integrationConfig;\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n constructor(\n private readonly integrationConfig: AwsCodeCommitIntegrationConfig,\n ) {}\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number | undefined;\n }): string {\n const resolved = defaultScmResolveUrl(options);\n return resolved;\n }\n resolveEditUrl(url: string): string {\n const parsedUrl = new URL(url);\n const pathMatch = parsedUrl.pathname.match(\n /^\\/codesuite\\/codecommit\\/repositories\\/([^\\/]+)\\//,\n );\n if (!pathMatch) {\n throw new Error(``);\n }\n const [, repositoryName] = pathMatch;\n return replaceCodeCommitUrlType(url, repositoryName, 'edit');\n }\n}\n\n/**\n * Takes a CodeCommit URL and replaces the type part (blob, tree etc).\n *\n * @param url - The original URL\n * @param type - The desired type, e.g. 'blob', 'edit'\n * @public\n */\nexport function replaceCodeCommitUrlType(\n url: string,\n repositoryName: string,\n type: 'browse' | 'edit',\n): string {\n const newString = type === 'edit' ? `files/edit` : type;\n return url.replace(\n new RegExp(\n `\\/codesuite\\/codecommit\\/repositories\\/${repositoryName}\\/(browse|files\\/edit)\\/`,\n ),\n `/codesuite/codecommit/repositories/${repositoryName}/${newString}/`,\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\nconst VERSION_PREFIX_GIT_BRANCH = 'GB';\n\nexport class AzureUrl {\n /**\n * Parses an azure URL as copied from the browser address bar.\n *\n * Throws an error if the URL is not a valid azure repo URL.\n */\n static fromRepoUrl(repoUrl: string): AzureUrl {\n const url = new URL(repoUrl);\n\n let owner;\n let project;\n let repo;\n\n const parts = url.pathname.split('/').map(part => decodeURIComponent(part));\n if (parts[2] === '_git') {\n owner = parts[1];\n project = repo = parts[3];\n } else if (parts[3] === '_git') {\n owner = parts[1];\n project = parts[2];\n repo = parts[4];\n } else if (parts[4] === '_git') {\n owner = `${parts[1]}/${parts[2]}`;\n project = parts[3];\n repo = parts[5];\n }\n\n if (!owner || !project || !repo) {\n throw new Error('Azure URL must point to a git repository');\n }\n\n const path = url.searchParams.get('path') ?? undefined;\n\n let ref;\n const version = url.searchParams.get('version');\n if (version) {\n const prefix = version.slice(0, 2);\n if (prefix !== 'GB') {\n throw new Error('Azure URL version must point to a git branch');\n }\n ref = version.slice(2);\n }\n\n return new AzureUrl(url.origin, owner, project, repo, path, ref);\n }\n\n #origin: string;\n #owner: string;\n #project: string;\n #repo: string;\n #path?: string;\n #ref?: string;\n\n private constructor(\n origin: string,\n owner: string,\n project: string,\n repo: string,\n path?: string,\n ref?: string,\n ) {\n this.#origin = origin;\n this.#owner = owner;\n this.#project = project;\n this.#repo = repo;\n this.#path = path;\n this.#ref = ref;\n }\n\n #baseUrl = (...parts: string[]): URL => {\n const url = new URL(this.#origin);\n url.pathname = parts.map(part => encodeURIComponent(part)).join('/');\n return url;\n };\n\n /**\n * Returns a repo URL that can be used to navigate to the resource in azure.\n *\n * Throws an error if the URL is not a valid azure repo URL.\n */\n toRepoUrl(): string {\n let url;\n if (this.#project === this.#repo) {\n url = this.#baseUrl(this.#owner, '_git', this.#repo);\n } else {\n url = this.#baseUrl(this.#owner, this.#project, '_git', this.#repo);\n }\n\n if (this.#path) {\n url.searchParams.set('path', this.#path);\n }\n if (this.#ref) {\n url.searchParams.set('version', VERSION_PREFIX_GIT_BRANCH + this.#ref);\n }\n\n return url.toString();\n }\n\n /**\n * Returns the file download URL for this azure resource.\n *\n * Throws an error if the URL does not point to a file.\n */\n toFileUrl(): string {\n if (!this.#path) {\n throw new Error(\n 'Azure URL must point to a specific path to be able to download a file',\n );\n }\n\n const url = this.#baseUrl(\n this.#owner,\n this.#project,\n '_apis',\n 'git',\n 'repositories',\n this.#repo,\n 'items',\n );\n url.searchParams.set('api-version', '6.0');\n url.searchParams.set('path', this.#path);\n\n if (this.#ref) {\n url.searchParams.set('version', this.#ref);\n }\n\n return url.toString();\n }\n\n /**\n * Returns the archive download URL for this azure resource.\n *\n * Throws an error if the URL does not point to a repo.\n */\n toArchiveUrl(): string {\n const url = this.#baseUrl(\n this.#owner,\n this.#project,\n '_apis',\n 'git',\n 'repositories',\n this.#repo,\n 'items',\n );\n url.searchParams.set('recursionLevel', 'full');\n url.searchParams.set('download', 'true');\n url.searchParams.set('api-version', '6.0');\n\n if (this.#path) {\n url.searchParams.set('scopePath', this.#path);\n }\n if (this.#ref) {\n url.searchParams.set('version', this.#ref);\n }\n\n return url.toString();\n }\n\n /**\n * Returns the API url for fetching commits from a branch for this azure resource.\n *\n * Throws an error if the URL does not point to a commit.\n */\n toCommitsUrl(): string {\n const url = this.#baseUrl(\n this.#owner,\n this.#project,\n '_apis',\n 'git',\n 'repositories',\n this.#repo,\n 'commits',\n );\n url.searchParams.set('api-version', '6.0');\n\n if (this.#ref) {\n url.searchParams.set('searchCriteria.itemVersion.version', this.#ref);\n }\n\n return url.toString();\n }\n\n /**\n * Returns the name of the owner, a user or an organization.\n */\n getOwner(): string {\n return this.#owner;\n }\n\n /**\n * Returns the name of the project.\n */\n getProject(): string {\n return this.#project;\n }\n\n /**\n * Returns the name of the repo.\n */\n getRepo(): string {\n return this.#repo;\n }\n\n /**\n * Returns the file path within the repo if the URL contains one.\n */\n getPath(): string | undefined {\n return this.#path;\n }\n\n /**\n * Returns the git ref in the repo if the URL contains one.\n */\n getRef(): string | undefined {\n return this.#ref;\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 { Config } from '@backstage/config';\nimport { isValidHost } from '../helpers';\n\nconst AZURE_HOST = 'dev.azure.com';\n\n/**\n * The configuration parameters for a single Azure provider.\n *\n * @public\n */\nexport type AzureIntegrationConfig = {\n /**\n * The host of the target that this matches on, e.g. \"dev.azure.com\".\n *\n * Currently only \"dev.azure.com\" is supported.\n */\n host: string;\n\n /**\n * The authorization token to use for requests.\n *\n * If no token is specified, anonymous access is used.\n *\n * @deprecated Use `credentials` instead.\n */\n token?: string;\n\n /**\n * The credential to use for requests.\n *\n * If no credential is specified anonymous access is used.\n *\n * @deprecated Use `credentials` instead.\n */\n credential?: AzureDevOpsCredential;\n\n /**\n * The credentials to use for requests. If multiple credentials are specified the first one that matches the organization is used.\n * If not organization matches the first credential without an organization is used.\n *\n * If no credentials are specified at all, either a default credential (for Azure DevOps) or anonymous access (for Azure DevOps Server) is used.\n */\n credentials?: AzureDevOpsCredential[];\n\n /**\n * Signing key for commits\n */\n commitSigningKey?: string;\n};\n\n/**\n * The kind of Azure DevOps credential.\n * @public\n */\nexport type AzureDevOpsCredentialKind =\n | 'PersonalAccessToken'\n | 'ClientSecret'\n | 'ManagedIdentity'\n | 'ManagedIdentityClientAssertion';\n\n/**\n * Common fields for the Azure DevOps credentials.\n * @public\n */\nexport type AzureCredentialBase = {\n /**\n * The kind of credential.\n */\n kind: AzureDevOpsCredentialKind;\n /**\n * The Azure DevOps organizations for which to use this credential.\n */\n organizations?: string[];\n};\n\n/**\n * A client secret credential that was generated for an App Registration.\n * @public\n */\nexport type AzureClientSecretCredential = AzureCredentialBase & {\n kind: 'ClientSecret';\n /**\n * The Entra ID tenant\n */\n tenantId: string;\n /**\n * The client id\n */\n clientId: string;\n\n /**\n * The client secret\n */\n clientSecret: string;\n};\n\n/**\n * A client assertion credential that uses a managed identity to generate a client assertion (JWT).\n * @public\n */\nexport type AzureManagedIdentityClientAssertionCredential =\n AzureCredentialBase & {\n kind: 'ManagedIdentityClientAssertion';\n /**\n * The Entra ID tenant\n */\n tenantId: string;\n\n /**\n * The client ID of the app registration you want to authenticate as.\n */\n clientId: string;\n\n /**\n * The client ID of the managed identity used to generate a client assertion (JWT).\n * Set to \"system-assigned\" to automatically use the system-assigned managed identity.\n * For user-assigned managed identities, specify the client ID of the managed identity you want to use.\n */\n managedIdentityClientId: 'system-assigned' | string;\n };\n\n/**\n * A managed identity credential.\n * @public\n */\nexport type AzureManagedIdentityCredential = AzureCredentialBase & {\n kind: 'ManagedIdentity';\n /**\n * The clientId\n */\n clientId: 'system-assigned' | string;\n};\n\n/**\n * A personal access token credential.\n * @public\n */\nexport type PersonalAccessTokenCredential = AzureCredentialBase & {\n kind: 'PersonalAccessToken';\n personalAccessToken: string;\n};\n\n/**\n * The general shape of a credential that can be used to authenticate to Azure DevOps.\n * @public\n */\nexport type AzureDevOpsCredentialLike = Omit<\n Partial<AzureClientSecretCredential> &\n Partial<AzureManagedIdentityClientAssertionCredential> &\n Partial<AzureManagedIdentityCredential> &\n Partial<PersonalAccessTokenCredential>,\n 'kind'\n>;\n\n/**\n * Credential used to authenticate to Azure DevOps.\n * @public\n */\nexport type AzureDevOpsCredential =\n | AzureClientSecretCredential\n | AzureManagedIdentityClientAssertionCredential\n | AzureManagedIdentityCredential\n | PersonalAccessTokenCredential;\n\nconst AzureDevOpsCredentialFields = [\n 'clientId',\n 'clientSecret',\n 'managedIdentityClientId',\n 'tenantId',\n 'personalAccessToken',\n] as const;\ntype AzureDevOpsCredentialField = (typeof AzureDevOpsCredentialFields)[number];\n\nconst AzureDevopsCredentialFieldMap = new Map<\n AzureDevOpsCredentialKind,\n AzureDevOpsCredentialField[]\n>([\n ['ClientSecret', ['clientId', 'clientSecret', 'tenantId']],\n ['ManagedIdentity', ['clientId']],\n [\n 'ManagedIdentityClientAssertion',\n ['clientId', 'managedIdentityClientId', 'tenantId'],\n ],\n ['PersonalAccessToken', ['personalAccessToken']],\n]);\n\nfunction asAzureDevOpsCredential(\n credential: AzureDevOpsCredentialLike,\n): AzureDevOpsCredential {\n for (const entry of AzureDevopsCredentialFieldMap.entries()) {\n const [kind, requiredFields] = entry;\n\n const forbiddenFields = AzureDevOpsCredentialFields.filter(\n field => !requiredFields.includes(field as AzureDevOpsCredentialField),\n );\n\n if (\n requiredFields.every(field => credential[field] !== undefined) &&\n forbiddenFields.every(field => credential[field] === undefined)\n ) {\n return {\n kind,\n organizations: credential.organizations,\n ...requiredFields.reduce((acc, field) => {\n acc[field] = credential[field];\n return acc;\n }, {} as Record<string, any>),\n } as AzureDevOpsCredential;\n }\n }\n throw new Error('is not a valid credential');\n}\n\n/**\n * Reads a single Azure integration config.\n *\n * @param config - The config object of a single integration\n * @public\n */\nexport function readAzureIntegrationConfig(\n config: Config,\n): AzureIntegrationConfig {\n const host = config.getOptionalString('host') ?? AZURE_HOST;\n\n let credentialConfigs = config\n .getOptionalConfigArray('credentials')\n ?.map(credential => {\n const result: Partial<AzureDevOpsCredentialLike> = {\n organizations: credential.getOptionalStringArray('organizations'),\n personalAccessToken: credential\n .getOptionalString('personalAccessToken')\n ?.trim(),\n tenantId: credential.getOptionalString('tenantId')?.trim(),\n clientId: credential.getOptionalString('clientId')?.trim(),\n clientSecret: credential.getOptionalString('clientSecret')?.trim(),\n managedIdentityClientId: credential\n .getOptionalString('managedIdentityClientId')\n ?.trim(),\n };\n\n return result;\n });\n\n const token = config.getOptionalString('token')?.trim();\n\n if (\n config.getOptional('credential') !== undefined &&\n config.getOptional('credentials') !== undefined\n ) {\n throw new Error(\n `Invalid Azure integration config, 'credential' and 'credentials' cannot be used together. Use 'credentials' instead.`,\n );\n }\n\n if (\n config.getOptional('token') !== undefined &&\n config.getOptional('credentials') !== undefined\n ) {\n throw new Error(\n `Invalid Azure integration config, 'token' and 'credentials' cannot be used together. Use 'credentials' instead.`,\n );\n }\n\n if (token !== undefined) {\n const mapped = [{ personalAccessToken: token }];\n credentialConfigs = credentialConfigs?.concat(mapped) ?? mapped;\n }\n\n if (config.getOptional('credential') !== undefined) {\n const mapped = [\n {\n organizations: config.getOptionalStringArray(\n 'credential.organizations',\n ),\n token: config.getOptionalString('credential.token')?.trim(),\n tenantId: config.getOptionalString('credential.tenantId'),\n clientId: config.getOptionalString('credential.clientId'),\n clientSecret: config\n .getOptionalString('credential.clientSecret')\n ?.trim(),\n },\n ];\n credentialConfigs = credentialConfigs?.concat(mapped) ?? mapped;\n }\n\n if (!isValidHost(host)) {\n throw new Error(\n `Invalid Azure integration config, '${host}' is not a valid host`,\n );\n }\n\n let credentials: AzureDevOpsCredential[] | undefined = undefined;\n if (credentialConfigs !== undefined) {\n const errors = credentialConfigs\n ?.reduce((acc, credentialConfig, index) => {\n let error: string | undefined = undefined;\n try {\n asAzureDevOpsCredential(credentialConfig);\n } catch (e) {\n error = e.message;\n }\n\n if (error !== undefined) {\n acc.push(`credential at position ${index + 1} ${error}`);\n }\n\n return acc;\n }, Array.of<string>())\n .concat(\n Object.entries(\n credentialConfigs\n .filter(\n credential =>\n credential.organizations !== undefined &&\n credential.organizations.length > 0,\n )\n .reduce((acc, credential, index) => {\n credential.organizations?.forEach(organization => {\n if (!acc[organization]) {\n acc[organization] = [];\n }\n\n acc[organization].push(index + 1);\n });\n\n return acc;\n }, {} as Record<string, number[]>),\n )\n .filter(([_, indexes]) => indexes.length > 1)\n .reduce((acc, [org, indexes]) => {\n acc.push(\n `organization ${org} is specified multiple times in credentials at positions ${indexes\n .slice(0, indexes.length - 1)\n .join(', ')} and ${indexes[indexes.length - 1]}`,\n );\n return acc;\n }, Array.of<string>()),\n );\n\n if (errors?.length > 0) {\n throw new Error(\n `Invalid Azure integration config for ${host}: ${errors.join('; ')}`,\n );\n }\n\n credentials = credentialConfigs.map(credentialConfig =>\n asAzureDevOpsCredential(credentialConfig),\n );\n\n if (\n credentials.some(\n credential => credential.kind !== 'PersonalAccessToken',\n ) &&\n host !== AZURE_HOST\n ) {\n throw new Error(\n `Invalid Azure integration config for ${host}, only personal access tokens can be used with hosts other than ${AZURE_HOST}`,\n );\n }\n\n if (\n credentials.filter(\n credential =>\n credential.organizations === undefined ||\n credential.organizations.length === 0,\n ).length > 1\n ) {\n throw new Error(\n `Invalid Azure integration config for ${host}, you cannot specify multiple credentials without organizations`,\n );\n }\n }\n\n return {\n host,\n credentials,\n commitSigningKey: config.getOptionalString('commitSigningKey'),\n };\n}\n\n/**\n * Reads a set of Azure integration configs, and inserts some defaults for\n * public Azure if not specified.\n *\n * @param configs - All of the integration config objects\n * @public\n */\nexport function readAzureIntegrationConfigs(\n configs: Config[],\n): AzureIntegrationConfig[] {\n // First read all the explicit integrations\n const result = configs.map(readAzureIntegrationConfig);\n\n // If no explicit dev.azure.com integration was added, put one in the list as\n // a convenience\n if (!result.some(c => c.host === AZURE_HOST)) {\n result.push({ host: AZURE_HOST });\n }\n\n return result;\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 { basicIntegrations, isValidUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport { AzureUrl } from './AzureUrl';\nimport { AzureIntegrationConfig, readAzureIntegrationConfigs } from './config';\n\n/**\n * Microsoft Azure based integration.\n *\n * @public\n */\nexport class AzureIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<AzureIntegration> = ({ config }) => {\n const configs = readAzureIntegrationConfigs(\n config.getOptionalConfigArray('integrations.azure') ?? [],\n );\n\n return basicIntegrations(\n configs.map(c => new AzureIntegration(c)),\n i => i.config.host,\n );\n };\n\n constructor(private readonly integrationConfig: AzureIntegrationConfig) {}\n\n get type(): string {\n return 'azure';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): AzureIntegrationConfig {\n return this.integrationConfig;\n }\n\n /*\n * Azure repo URLs on the form with a `path` query param are treated specially.\n *\n * Example base URL: https://dev.azure.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml\n */\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n }): string {\n const { url, base } = options;\n\n // If we can parse the url, it is absolute - then return it verbatim\n if (isValidUrl(url)) {\n return url;\n }\n\n try {\n const azureUrl = AzureUrl.fromRepoUrl(base);\n const newUrl = new URL(base);\n\n // We lean on the URL path resolution logic to resolve the path param\n const mockBaseUrl = new URL(`https://a.com${azureUrl.getPath() ?? ''}`);\n const updatedPath = new URL(url, mockBaseUrl).pathname;\n newUrl.searchParams.set('path', updatedPath);\n\n if (options.lineNumber) {\n newUrl.searchParams.set('line', String(options.lineNumber));\n newUrl.searchParams.set('lineEnd', String(options.lineNumber + 1));\n newUrl.searchParams.set('lineStartColumn', '1');\n newUrl.searchParams.set('lineEndColumn', '1');\n }\n\n return newUrl.toString();\n } catch {\n // If not an actual file path within a repo, treat the URL as raw\n return new URL(url, base).toString();\n }\n }\n\n resolveEditUrl(url: string): string {\n // TODO: Implement edit URL for Azure, fallback to view url as I don't know\n // how azure works.\n return url;\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 { Config } from '@backstage/config';\n\nconst BITBUCKET_CLOUD_HOST = 'bitbucket.org';\nconst BITBUCKET_CLOUD_API_BASE_URL = 'https://api.bitbucket.org/2.0';\n\n/**\n * The configuration parameters for a single Bitbucket Cloud API provider.\n *\n * @public\n */\nexport type BitbucketCloudIntegrationConfig = {\n /**\n * Constant. bitbucket.org\n */\n host: string;\n\n /**\n * Constant. https://api.bitbucket.org/2.0\n */\n apiBaseUrl: string;\n\n /**\n * The username to use for requests to Bitbucket Cloud (bitbucket.org).\n */\n username?: string;\n\n /**\n * Authentication with Bitbucket Cloud (bitbucket.org) is done using app passwords.\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/app-passwords/\n */\n appPassword?: string;\n\n /**\n * The access token to use for requests to Bitbucket Cloud (bitbucket.org).\n */\n token?: string;\n\n /** PGP private key for signing commits. */\n commitSigningKey?: string;\n};\n\n/**\n * Reads a single Bitbucket Cloud integration config.\n *\n * @param config - The config object of a single integration\n * @public\n */\nexport function readBitbucketCloudIntegrationConfig(\n config: Config,\n): BitbucketCloudIntegrationConfig {\n const host = BITBUCKET_CLOUD_HOST;\n const apiBaseUrl = BITBUCKET_CLOUD_API_BASE_URL;\n // If config is provided, we assume authenticated access is desired\n // (as the anonymous one is provided by default).\n const username = config.getString('username');\n const appPassword = config.getString('appPassword')?.trim();\n\n return {\n host,\n apiBaseUrl,\n username,\n appPassword,\n commitSigningKey: config.getOptionalString('commitSigningKey'),\n };\n}\n\n/**\n * Reads a set of Bitbucket Cloud integration configs,\n * and inserts one for public Bitbucket Cloud if none specified.\n *\n * @param configs - All of the integration config objects\n * @public\n */\nexport function readBitbucketCloudIntegrationConfigs(\n configs: Config[],\n): BitbucketCloudIntegrationConfig[] {\n // First read all the explicit integrations\n const result = configs.map(readBitbucketCloudIntegrationConfig);\n\n // If no explicit bitbucket.org integration was added,\n // put one in the list as a convenience\n if (result.length === 0) {\n result.push({\n host: BITBUCKET_CLOUD_HOST,\n apiBaseUrl: BITBUCKET_CLOUD_API_BASE_URL,\n });\n }\n\n return result;\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 parseGitUrl from 'git-url-parse';\nimport { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport {\n BitbucketCloudIntegrationConfig,\n readBitbucketCloudIntegrationConfigs,\n} from './config';\n\n/**\n * A Bitbucket Cloud based integration.\n *\n * @public\n */\nexport class BitbucketCloudIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<BitbucketCloudIntegration> = ({\n config,\n }) => {\n const configs = readBitbucketCloudIntegrationConfigs(\n config.getOptionalConfigArray('integrations.bitbucketCloud') ?? [],\n );\n return basicIntegrations(\n configs.map(c => new BitbucketCloudIntegration(c)),\n i => i.config.host,\n );\n };\n\n constructor(\n private readonly integrationConfig: BitbucketCloudIntegrationConfig,\n ) {}\n\n get type(): string {\n return 'bitbucketCloud';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): BitbucketCloudIntegrationConfig {\n return this.integrationConfig;\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n }): string {\n const resolved = defaultScmResolveUrl(options);\n\n // Bitbucket Cloud line numbers use the syntax #lines-42, rather than #L42\n if (options.lineNumber) {\n const url = new URL(resolved);\n\n url.hash = `lines-${options.lineNumber}`;\n return url.toString();\n }\n\n return resolved;\n }\n\n resolveEditUrl(url: string): string {\n const urlData = parseGitUrl(url);\n const editUrl = new URL(url);\n\n editUrl.searchParams.set('mode', 'edit');\n editUrl.searchParams.set('at', urlData.ref);\n return editUrl.toString();\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 { Config } from '@backstage/config';\nimport { trimEnd } from 'lodash';\nimport { isValidHost } from '../helpers';\n\nconst BITBUCKET_HOST = 'bitbucket.org';\nconst BITBUCKET_API_BASE_URL = 'https://api.bitbucket.org/2.0';\n\n/**\n * The configuration parameters for a single Bitbucket API provider.\n *\n * @public\n * @deprecated bitbucket integration replaced by integrations bitbucketCloud and bitbucketServer.\n */\nexport type BitbucketIntegrationConfig = {\n /**\n * The host of the target that this matches on, e.g. \"bitbucket.org\"\n */\n host: string;\n\n /**\n * The base URL of the API of this provider, e.g. \"https://api.bitbucket.org/2.0\",\n * with no trailing slash.\n *\n * Values omitted at the optional property at the app-config will be deduced\n * from the \"host\" value.\n */\n apiBaseUrl: string;\n\n /**\n * The authorization token to use for requests to a Bitbucket Server provider.\n *\n * See https://confluence.atlassian.com/bitbucketserver/personal-access-tokens-939515499.html\n *\n * If no token is specified, anonymous access is used.\n */\n token?: string;\n\n /**\n * The username to use for requests to Bitbucket Cloud (bitbucket.org).\n */\n username?: string;\n\n /**\n * Authentication with Bitbucket Cloud (bitbucket.org) is done using app passwords.\n *\n * See https://support.atlassian.com/bitbucket-cloud/docs/app-passwords/\n */\n appPassword?: string;\n\n /**\n * Signing key for commits\n */\n commitSigningKey?: string;\n};\n\n/**\n * Reads a single Bitbucket integration config.\n *\n * @param config - The config object of a single integration\n * @public\n * @deprecated bitbucket integration replaced by integrations bitbucketCloud and bitbucketServer.\n */\nexport function readBitbucketIntegrationConfig(\n config: Config,\n): BitbucketIntegrationConfig {\n const host = config.getOptionalString('host') ?? BITBUCKET_HOST;\n let apiBaseUrl = config.getOptionalString('apiBaseUrl');\n const token = config.getOptionalString('token')?.trim();\n const username = config.getOptionalString('username');\n const appPassword = config.getOptionalString('appPassword')?.trim();\n\n if (!isValidHost(host)) {\n throw new Error(\n `Invalid Bitbucket integration config, '${host}' is not a valid host`,\n );\n }\n\n if (apiBaseUrl) {\n apiBaseUrl = trimEnd(apiBaseUrl, '/');\n } else if (host === BITBUCKET_HOST) {\n apiBaseUrl = BITBUCKET_API_BASE_URL;\n } else {\n apiBaseUrl = `https://${host}/rest/api/1.0`;\n }\n\n return {\n host,\n apiBaseUrl,\n token,\n username,\n appPassword,\n commitSigningKey: config.getOptionalString('commitSigningKey'),\n };\n}\n\n/**\n * Reads a set of Bitbucket integration configs, and inserts some defaults for\n * public Bitbucket if not specified.\n *\n * @param configs - All of the integration config objects\n * @public\n * @deprecated bitbucket integration replaced by integrations bitbucketCloud and bitbucketServer.\n */\nexport function readBitbucketIntegrationConfigs(\n configs: Config[],\n): BitbucketIntegrationConfig[] {\n // First read all the explicit integrations\n const result = configs.map(readBitbucketIntegrationConfig);\n\n // If no explicit bitbucket.org integration was added, put one in the list as\n // a convenience\n if (!result.some(c => c.host === BITBUCKET_HOST)) {\n result.push({\n host: BITBUCKET_HOST,\n apiBaseUrl: BITBUCKET_API_BASE_URL,\n });\n }\n\n return result;\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 parseGitUrl from 'git-url-parse';\nimport { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport {\n BitbucketIntegrationConfig,\n readBitbucketIntegrationConfigs,\n} from './config';\n\n/**\n * A Bitbucket based integration.\n *\n * @public\n * @deprecated replaced by the integrations bitbucketCloud and bitbucketServer.\n */\nexport class BitbucketIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<BitbucketIntegration> = ({\n config,\n }) => {\n const configs = readBitbucketIntegrationConfigs(\n config.getOptionalConfigArray('integrations.bitbucket') ?? [\n // if integrations.bitbucket was not used assume the use was migrated to the new configs\n // and backport for the deprecated integration to be usable for other parts of the system\n // until these got migrated\n ...(config.getOptionalConfigArray('integrations.bitbucketCloud') ?? []),\n ...(config.getOptionalConfigArray('integrations.bitbucketServer') ??\n []),\n ],\n );\n return basicIntegrations(\n configs.map(c => new BitbucketIntegration(c)),\n i => i.config.host,\n );\n };\n\n constructor(private readonly integrationConfig: BitbucketIntegrationConfig) {}\n\n get type(): string {\n return 'bitbucket';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): BitbucketIntegrationConfig {\n return this.integrationConfig;\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n }): string {\n const resolved = defaultScmResolveUrl(options);\n if (!options.lineNumber) {\n return resolved;\n }\n\n const url = new URL(resolved);\n\n if (this.integrationConfig.host === 'bitbucket.org') {\n // Bitbucket Cloud uses the syntax #lines-{start}[:{end}][,...]\n url.hash = `lines-${options.lineNumber}`;\n } else {\n // Bitbucket Server uses the syntax #{start}[-{end}][,...]\n url.hash = `${options.lineNumber}`;\n }\n\n return url.toString();\n }\n\n resolveEditUrl(url: string): string {\n const urlData = parseGitUrl(url);\n const editUrl = new URL(url);\n\n editUrl.searchParams.set('mode', 'edit');\n // TODO: Not sure what spa=0 does, at least bitbucket.org doesn't support it\n // but this is taken over from the initial implementation.\n editUrl.searchParams.set('spa', '0');\n editUrl.searchParams.set('at', urlData.ref);\n return editUrl.toString();\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 { Config } from '@backstage/config';\nimport { trimEnd } from 'lodash';\nimport { isValidHost } from '../helpers';\n\n/**\n * The configuration parameters for a single Bitbucket Server API provider.\n *\n * @public\n */\nexport type BitbucketServerIntegrationConfig = {\n /**\n * The host of the target that this matches on, e.g. \"bitbucket.company.com\"\n */\n host: string;\n\n /**\n * The base URL of the API of this provider, e.g. \"https://<host>/rest/api/1.0\",\n * with no trailing slash.\n *\n * The API will always be preferred if both its base URL and a token are\n * present.\n */\n apiBaseUrl: string;\n\n /**\n * The authorization token to use for requests to a Bitbucket Server provider.\n *\n * See https://confluence.atlassian.com/bitbucketserver/personal-access-tokens-939515499.html\n *\n * If no token is specified, anonymous access is used.\n */\n token?: string;\n\n /**\n * The credentials for Basic Authentication for requests to a Bitbucket Server provider.\n *\n * If `token` was provided, it will be preferred.\n *\n * See https://developer.atlassian.com/server/bitbucket/how-tos/command-line-rest/#authentication\n */\n username?: string;\n\n /**\n * The credentials for Basic Authentication for requests to a Bitbucket Server provider.\n *\n * If `token` was provided, it will be preferred.\n *\n * See https://developer.atlassian.com/server/bitbucket/how-tos/command-line-rest/#authentication\n */\n password?: string;\n\n /**\n * Signing key for commits\n */\n commitSigningKey?: string;\n};\n\n/**\n * Reads a single Bitbucket Server integration config.\n *\n * @param config - The config object of a single integration\n * @public\n */\nexport function readBitbucketServerIntegrationConfig(\n config: Config,\n): BitbucketServerIntegrationConfig {\n const host = config.getString('host');\n let apiBaseUrl = config.getOptionalString('apiBaseUrl');\n const token = config.getOptionalString('token')?.trim();\n const username = config.getOptionalString('username');\n const password = config.getOptionalString('password');\n\n if (!isValidHost(host)) {\n throw new Error(\n `Invalid Bitbucket Server integration config, '${host}' is not a valid host`,\n );\n }\n\n if (apiBaseUrl) {\n apiBaseUrl = trimEnd(apiBaseUrl, '/');\n } else {\n apiBaseUrl = `https://${host}/rest/api/1.0`;\n }\n\n return {\n host,\n apiBaseUrl,\n token,\n username,\n password,\n commitSigningKey: config.getOptionalString('commitSigningKey'),\n };\n}\n\n/**\n * Reads a set of Bitbucket Server integration configs.\n *\n * @param configs - All of the integration config objects\n * @public\n */\nexport function readBitbucketServerIntegrationConfigs(\n configs: Config[],\n): BitbucketServerIntegrationConfig[] {\n // Read all the explicit integrations\n // No default integration will be added\n return configs.map(readBitbucketServerIntegrationConfig);\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 { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport {\n BitbucketServerIntegrationConfig,\n readBitbucketServerIntegrationConfigs,\n} from './config';\n\n/**\n * A Bitbucket Server based integration.\n *\n * @public\n */\nexport class BitbucketServerIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<BitbucketServerIntegration> = ({\n config,\n }) => {\n const configs = readBitbucketServerIntegrationConfigs(\n config.getOptionalConfigArray('integrations.bitbucketServer') ?? [],\n );\n return basicIntegrations(\n configs.map(c => new BitbucketServerIntegration(c)),\n i => i.config.host,\n );\n };\n\n constructor(\n private readonly integrationConfig: BitbucketServerIntegrationConfig,\n ) {}\n\n get type(): string {\n return 'bitbucketServer';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): BitbucketServerIntegrationConfig {\n return this.integrationConfig;\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n }): string {\n const resolved = defaultScmResolveUrl(options);\n\n // Bitbucket Server line numbers use the syntax #42, rather than #L42\n if (options.lineNumber) {\n const url = new URL(resolved);\n\n url.hash = options.lineNumber.toString();\n return url.toString();\n }\n\n return resolved;\n }\n\n resolveEditUrl(url: string): string {\n // Bitbucket Server doesn't support deep linking to edit mode, therefore there's nothing to do here.\n // We just remove query parameters since they cause issues with TechDocs edit button.\n if (url.includes('?')) {\n return url.substring(0, url.indexOf('?'));\n }\n return url;\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 */\n\nimport { Config } from '@backstage/config';\nimport { trimEnd } from 'lodash';\nimport { isValidHost, isValidUrl } from '../helpers';\n\n/**\n * The configuration parameters for a single Gerrit API provider.\n *\n * @public\n */\nexport type GerritIntegrationConfig = {\n /**\n * The host of the target that this matches on, e.g. \"gerrit-review.com\"\n */\n host: string;\n\n /**\n * The optional base URL of the Gerrit instance. It is assumed that https\n * is used and that the base path is \"/\" on the host. If that is not the\n * case set the complete base url to the gerrit instance, e.g.\n * \"https://gerrit-review.com/gerrit\". This is the url that you would open\n * in a browser.\n */\n baseUrl?: string;\n\n /**\n * The optional base url to use for cloning a repository. If not set the\n * baseUrl will be used.\n */\n cloneUrl?: string;\n\n /**\n * Disable the edit url feature for Gerrit version less than 3.9.\n */\n disableEditUrl?: boolean;\n\n /**\n * Base url for Gitiles. This is needed for creating a valid\n * user-friendly url that can be used for browsing the content of the\n * provider.\n */\n gitilesBaseUrl: string;\n\n /**\n * The username to use for requests to gerrit.\n */\n username?: string;\n\n /**\n * The password or http token to use for authentication.\n */\n password?: string;\n\n /**\n * The signing key to use for signing commits.\n */\n commitSigningKey?: string;\n};\n\n/**\n * Reads a single Gerrit integration config.\n *\n * @param config - The config object of a single integration\n *\n * @public\n */\nexport function readGerritIntegrationConfig(\n config: Config,\n): GerritIntegrationConfig {\n const host = config.getString('host');\n let baseUrl = config.getOptionalString('baseUrl');\n let cloneUrl = config.getOptionalString('cloneUrl');\n const disableEditUrl = config.getOptionalBoolean('disableEditUrl');\n let gitilesBaseUrl = config.getString('gitilesBaseUrl');\n const username = config.getOptionalString('username');\n const password = config.getOptionalString('password')?.trim();\n\n if (!isValidHost(host)) {\n throw new Error(\n `Invalid Gerrit integration config, '${host}' is not a valid host`,\n );\n } else if (baseUrl && !isValidUrl(baseUrl)) {\n throw new Error(\n `Invalid Gerrit integration config, '${baseUrl}' is not a valid baseUrl`,\n );\n } else if (cloneUrl && !isValidUrl(cloneUrl)) {\n throw new Error(\n `Invalid Gerrit integration config, '${cloneUrl}' is not a valid cloneUrl`,\n );\n } else if (!isValidUrl(gitilesBaseUrl)) {\n throw new Error(\n `Invalid Gerrit integration config, '${gitilesBaseUrl}' is not a valid gitilesBaseUrl`,\n );\n }\n if (baseUrl) {\n baseUrl = trimEnd(baseUrl, '/');\n } else {\n baseUrl = `https://${host}`;\n }\n if (cloneUrl) {\n cloneUrl = trimEnd(cloneUrl, '/');\n } else {\n cloneUrl = baseUrl;\n }\n\n gitilesBaseUrl = trimEnd(gitilesBaseUrl, '/');\n\n return {\n host,\n baseUrl,\n cloneUrl,\n disableEditUrl,\n gitilesBaseUrl,\n username,\n password,\n commitSigningKey: config.getOptionalString('commitSigningKey'),\n };\n}\n\n/**\n * Reads a set of Gerrit integration configs.\n *\n * @param configs - All of the integration config objects\n *\n * @public\n */\nexport function readGerritIntegrationConfigs(\n configs: Config[],\n): GerritIntegrationConfig[] {\n return configs.map(readGerritIntegrationConfig);\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 { join, takeWhile, trimEnd, trimStart } from 'lodash';\nimport { GerritIntegrationConfig } from './config';\n\nconst GERRIT_BODY_PREFIX = \")]}'\";\n\n/**\n * Parse a Gitiles URL and return branch, file path and project.\n *\n * @remarks\n *\n * Gerrit only handles code reviews so it does not have a native way to browse\n * or showing the content of gits. Image if Github only had the \"pull requests\"\n * tab.\n *\n * Any source code browsing is instead handled by optional services outside\n * Gerrit. The url format chosen for the Gerrit url reader is the one used by\n * the Gitiles project. Gerrit will work perfectly with Backstage without\n * having Gitiles installed but there are some places in the Backstage GUI\n * with links to the url used by the url reader. These will not work unless\n * the urls point to an actual Gitiles installation.\n *\n * Gitiles url:\n * https://g.com/optional_path/\\{project\\}/+/refs/heads/\\{branch\\}/\\{filePath\\}\n * https://g.com/a/optional_path/\\{project\\}/+/refs/heads/\\{branch\\}/\\{filePath\\}\n *\n *\n * @param url - An URL pointing to a file stored in git.\n * @public\n * @deprecated `parseGerritGitilesUrl` is deprecated. Use\n * {@link parseGitilesUrlRef} instead.\n */\nexport function parseGerritGitilesUrl(\n config: GerritIntegrationConfig,\n url: string,\n): { branch: string; filePath: string; project: string } {\n const baseUrlParse = new URL(config.gitilesBaseUrl!);\n const urlParse = new URL(url);\n\n // Remove the gerrit authentication prefix '/a/' from the url\n // In case of the gitilesBaseUrl is https://review.gerrit.com/plugins/gitiles\n // and the url provided is https://review.gerrit.com/a/plugins/gitiles/...\n // remove the prefix only if the pathname start with '/a/'\n const urlPath = urlParse.pathname\n .substring(urlParse.pathname.startsWith('/a/') ? 2 : 0)\n .replace(baseUrlParse.pathname, '');\n\n const parts = urlPath.split('/').filter(p => !!p);\n\n const projectEndIndex = parts.indexOf('+');\n\n if (projectEndIndex <= 0) {\n throw new Error(`Unable to parse project from url: ${url}`);\n }\n const project = trimStart(parts.slice(0, projectEndIndex).join('/'), '/');\n\n const branchIndex = parts.indexOf('heads');\n if (branchIndex <= 0) {\n throw new Error(`Unable to parse branch from url: ${url}`);\n }\n const branch = parts[branchIndex + 1];\n const filePath = parts.slice(branchIndex + 2).join('/');\n\n return {\n branch,\n filePath: filePath === '' ? '/' : filePath,\n project,\n };\n}\n\n/**\n * Parses Gitiles urls and returns the following:\n *\n * - The project\n * - The type of ref. I.e: branch name, SHA, HEAD or tag.\n * - The file path from the repo root.\n * - The base path as the path that points to the repo root.\n *\n * Supported types of gitiles urls that point to:\n *\n * - Branches\n * - Tags\n * - A commit SHA\n * - HEAD\n *\n * @param config - A Gerrit provider config.\n * @param url - An url to a file or folder in Gitiles.\n * @public\n */\nexport function parseGitilesUrlRef(\n config: GerritIntegrationConfig,\n url: string,\n): {\n project: string;\n path: string;\n ref: string;\n refType: 'sha' | 'branch' | 'tag' | 'head';\n basePath: string;\n} {\n const baseUrlParse = new URL(config.gitilesBaseUrl!);\n const urlParse = new URL(url);\n // Remove the gerrit authentication prefix '/a/' from the url\n // In case of the gitilesBaseUrl is https://review.gerrit.com/plugins/gitiles\n // and the url provided is https://review.gerrit.com/a/plugins/gitiles/...\n // remove the prefix only if the pathname start with '/a/'\n const urlPath = trimStart(\n urlParse.pathname\n .substring(urlParse.pathname.startsWith('/a/') ? 2 : 0)\n .replace(baseUrlParse.pathname, ''),\n '/',\n );\n\n // Find the project by taking everything up to \"/+/\".\n const parts = urlPath.split('/').filter(p => !!p);\n const projectParts = takeWhile(parts, p => p !== '+');\n if (projectParts.length === 0) {\n throw new Error(`Unable to parse gitiles url: ${url}`);\n }\n // Also remove the \"+\" after the project.\n const rest = parts.slice(projectParts.length + 1);\n const project = join(projectParts, '/');\n\n // match <project>/+/HEAD/<path>\n if (rest.length > 0 && rest[0] === 'HEAD') {\n const ref = rest.shift()!;\n const path = join(rest, '/');\n return {\n project,\n ref,\n refType: 'head' as const,\n path: path || '/',\n basePath: trimEnd(url.replace(path, ''), '/'),\n };\n }\n // match <project>/+/<sha>/<path>\n if (rest.length > 0 && rest[0].length === 40) {\n const ref = rest.shift()!;\n const path = join(rest, '/');\n return {\n project,\n ref,\n refType: 'sha' as const,\n path: path || '/',\n basePath: trimEnd(url.replace(path, ''), '/'),\n };\n }\n const remainingPath = join(rest, '/');\n // Regexp for matching \"refs/tags/<tag>\" or \"refs/heads/<branch>/\"\n const refsRegexp = /^refs\\/(?<refsReference>heads|tags)\\/(?<ref>.*?)(\\/|$)/;\n const result = refsRegexp.exec(remainingPath);\n if (result) {\n const matchString = result[0];\n let refType;\n const { refsReference, ref } = result.groups || {};\n const path = remainingPath.replace(matchString, '');\n switch (refsReference) {\n case 'heads':\n refType = 'branch' as const;\n break;\n case 'tags':\n refType = 'tag' as const;\n break;\n default:\n throw new Error(`Unable to parse gitiles url: ${url}`);\n }\n return {\n project,\n ref,\n refType,\n path: path || '/',\n basePath: trimEnd(url.replace(path, ''), '/'),\n };\n }\n throw new Error(`Unable to parse gitiles : ${url}`);\n}\n\n/**\n * Build a Gerrit Gitiles url that targets a specific path.\n *\n * @param config - A Gerrit provider config.\n * @param project - The name of the git project\n * @param branch - The branch we will target.\n * @param filePath - The absolute file path.\n * @public\n */\nexport function buildGerritGitilesUrl(\n config: GerritIntegrationConfig,\n project: string,\n branch: string,\n filePath: string,\n): string {\n return `${\n config.gitilesBaseUrl\n }/${project}/+/refs/heads/${branch}/${trimStart(filePath, '/')}`;\n}\n\n/**\n * Build a Gerrit Gitiles url that targets a specific path.\n *\n * @param config - A Gerrit provider config.\n * @param project - The name of the git project\n * @param branch - The branch we will target.\n * @param filePath - The absolute file path.\n * @public\n */\nexport function buildGerritEditUrl(\n config: GerritIntegrationConfig,\n project: string,\n branch: string,\n filePath: string,\n): string {\n return `${\n config.baseUrl\n }/admin/repos/edit/repo/${project}/branch/refs/heads/${branch}/file/${trimStart(\n filePath,\n '/',\n )}`;\n}\n\n/**\n * Build a Gerrit Gitiles archive url that targets a specific branch and path\n *\n * @param config - A Gerrit provider config.\n * @param project - The name of the git project\n * @param branch - The branch we will target.\n * @param filePath - The absolute file path.\n * @public\n * @deprecated `buildGerritGitilesArchiveUrl` is deprecated. Use\n * {@link buildGerritGitilesArchiveUrlFromLocation} instead.\n */\nexport function buildGerritGitilesArchiveUrl(\n config: GerritIntegrationConfig,\n project: string,\n branch: string,\n filePath: string,\n): string {\n const archiveName =\n filePath === '/' || filePath === '' ? '.tar.gz' : `/${filePath}.tar.gz`;\n return `${getGitilesAuthenticationUrl(\n config,\n )}/${project}/+archive/refs/heads/${branch}${archiveName}`;\n}\n\n/**\n * Build a Gerrit Gitiles archive url from a Gitiles url.\n *\n * @param config - A Gerrit provider config.\n * @param url - The gitiles url\n * @public\n */\nexport function buildGerritGitilesArchiveUrlFromLocation(\n config: GerritIntegrationConfig,\n url: string,\n): string {\n const {\n path: filePath,\n ref,\n project,\n refType,\n } = parseGitilesUrlRef(config, url);\n const archiveName =\n filePath === '/' || filePath === '' ? '.tar.gz' : `/${filePath}.tar.gz`;\n if (refType === 'branch') {\n return `${getGitilesAuthenticationUrl(\n config,\n )}/${project}/+archive/refs/heads/${ref}${archiveName}`;\n }\n if (refType === 'sha') {\n return `${getGitilesAuthenticationUrl(\n config,\n )}/${project}/+archive/${ref}${archiveName}`;\n }\n throw new Error(`Unsupported gitiles ref type: ${refType}`);\n}\n\n/**\n * Return the authentication prefix.\n *\n * @remarks\n *\n * To authenticate with a password the API url must be prefixed with \"/a/\".\n * If no password is set anonymous access (without the prefix) will\n * be used.\n *\n * @param config - A Gerrit provider config.\n * @public\n */\nexport function getAuthenticationPrefix(\n config: GerritIntegrationConfig,\n): string {\n return config.password ? '/a/' : '/';\n}\n\n/**\n * Return the authentication gitiles url.\n *\n * @remarks\n *\n * To authenticate with a password the API url must be prefixed with \"/a/\".\n * If no password is set anonymous access (without the prefix) will\n * be used.\n *\n * @param config - A Gerrit provider config.\n * @public\n */\nexport function getGitilesAuthenticationUrl(\n config: GerritIntegrationConfig,\n): string {\n if (!config.baseUrl || !config.gitilesBaseUrl) {\n throw new Error(\n 'Unexpected Gerrit config values. baseUrl or gitilesBaseUrl not set.',\n );\n }\n if (config.gitilesBaseUrl.startsWith(config.baseUrl)) {\n return config.gitilesBaseUrl.replace(\n config.baseUrl.concat('/'),\n config.baseUrl.concat(getAuthenticationPrefix(config)),\n );\n }\n if (config.password) {\n throw new Error(\n 'Since the baseUrl (Gerrit) is not part of the gitilesBaseUrl, an authentication URL could not be constructed.',\n );\n }\n return config.gitilesBaseUrl!;\n}\n\n/**\n * Return the url to get branch info from the Gerrit API.\n *\n * @param config - A Gerrit provider config.\n * @param url - An url pointing to a file in git.\n * @public\n */\nexport function getGerritBranchApiUrl(\n config: GerritIntegrationConfig,\n url: string,\n) {\n const { branch, project } = parseGerritGitilesUrl(config, url);\n\n return `${config.baseUrl}${getAuthenticationPrefix(\n config,\n )}projects/${encodeURIComponent(project)}/branches/${branch}`;\n}\n\n/**\n * Return the url to clone the repo that is referenced by the url.\n *\n * @param url - An url pointing to a file in git.\n * @public\n */\nexport function getGerritCloneRepoUrl(\n config: GerritIntegrationConfig,\n url: string,\n) {\n const { project } = parseGerritGitilesUrl(config, url);\n\n return `${config.cloneUrl}${getAuthenticationPrefix(config)}${project}`;\n}\n\n/**\n * Return the url to fetch the contents of a file using the Gerrit API.\n *\n * @param config - A Gerrit provider config.\n * @param url - An url pointing to a file in git.\n * @public\n */\nexport function getGerritFileContentsApiUrl(\n config: GerritIntegrationConfig,\n url: string,\n) {\n const { ref, refType, path, project } = parseGitilesUrlRef(config, url);\n\n // https://gerrit-review.googlesource.com/Documentation/rest-api-projects.html#get-content\n if (refType === 'branch') {\n return `${config.baseUrl}${getAuthenticationPrefix(\n config,\n )}projects/${encodeURIComponent(\n project,\n )}/branches/${ref}/files/${encodeURIComponent(path)}/content`;\n }\n // https://gerrit-review.googlesource.com/Documentation/rest-api-projects.html#get-content-from-commit\n if (refType === 'sha') {\n return `${config.baseUrl}${getAuthenticationPrefix(\n config,\n )}projects/${encodeURIComponent(\n project,\n )}/commits/${ref}/files/${encodeURIComponent(path)}/content`;\n }\n throw new Error(`Unsupported gitiles ref type: ${refType}`);\n}\n\n/**\n * Return the url to query available projects using the Gerrit API.\n *\n * @param config - A Gerrit provider config.\n * @public\n */\nexport function getGerritProjectsApiUrl(config: GerritIntegrationConfig) {\n return `${config.baseUrl}${getAuthenticationPrefix(config)}projects/`;\n}\n\n/**\n * Return request headers for a Gerrit provider.\n *\n * @param config - A Gerrit provider config\n * @public\n */\nexport function getGerritRequestOptions(config: GerritIntegrationConfig): {\n headers?: Record<string, string>;\n} {\n const headers: Record<string, string> = {};\n\n if (!config.password) {\n return headers;\n }\n const buffer = Buffer.from(`${config.username}:${config.password}`, 'utf8');\n headers.Authorization = `Basic ${buffer.toString('base64')}`;\n return {\n headers,\n };\n}\n\n/**\n * Parse the json response from Gerrit and strip the magic prefix.\n *\n * @remarks\n *\n * To prevent against XSSI attacks the JSON response body from Gerrit starts\n * with a magic prefix that must be stripped before it can be fed to a JSON\n * parser.\n *\n * @param response - An API response.\n * @public\n */\nexport async function parseGerritJsonResponse(\n response: Response,\n): Promise<unknown> {\n const responseBody = await response.text();\n if (responseBody.startsWith(GERRIT_BODY_PREFIX)) {\n try {\n return JSON.parse(responseBody.slice(GERRIT_BODY_PREFIX.length));\n } catch (ex) {\n throw new Error(\n `Invalid response from Gerrit: ${responseBody.slice(0, 10)} - ${ex}`,\n );\n }\n }\n throw new Error(\n `Gerrit JSON body prefix missing. Found: ${responseBody.slice(0, 10)}`,\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 */\n\nimport { basicIntegrations } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport {\n GerritIntegrationConfig,\n readGerritIntegrationConfigs,\n} from './config';\nimport { buildGerritEditUrl, parseGitilesUrlRef } from './core';\n\n/**\n * A Gerrit based integration.\n *\n * @public\n */\nexport class GerritIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<GerritIntegration> = ({ config }) => {\n const configs = readGerritIntegrationConfigs(\n config.getOptionalConfigArray('integrations.gerrit') ?? [],\n );\n return basicIntegrations(\n configs.map(c => new GerritIntegration(c)),\n i => i.config.host,\n );\n };\n\n constructor(private readonly integrationConfig: GerritIntegrationConfig) {}\n\n get type(): string {\n return 'gerrit';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): GerritIntegrationConfig {\n return this.integrationConfig;\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n }): string {\n const { url, base, lineNumber } = options;\n let updated;\n if (url.startsWith('/')) {\n const { basePath } = parseGitilesUrlRef(this.config, base);\n return basePath + url;\n }\n if (url) {\n updated = new URL(url, base);\n } else {\n updated = new URL(base);\n }\n if (lineNumber) {\n updated.hash = lineNumber.toString();\n }\n return updated.toString();\n }\n\n resolveEditUrl(url: string): string {\n if (this.config.disableEditUrl) {\n return url;\n }\n\n const parsed = parseGitilesUrlRef(this.config, url);\n return buildGerritEditUrl(\n this.config,\n parsed.project,\n parsed.ref,\n parsed.path,\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 { Config } from '@backstage/config';\nimport { trimEnd } from 'lodash';\nimport { isValidHost, isValidUrl } from '../helpers';\n\nconst GITLAB_HOST = 'gitlab.com';\nconst GITLAB_API_BASE_URL = 'https://gitlab.com/api/v4';\n\n/**\n * The configuration parameters for a single GitLab integration.\n *\n * @public\n */\nexport type GitLabIntegrationConfig = {\n /**\n * The host of the target that this matches on, e.g. `gitlab.com`.\n */\n host: string;\n\n /**\n * The base URL of the API of this provider, e.g.\n * `https://gitlab.com/api/v4`, with no trailing slash.\n *\n * May be omitted specifically for public GitLab; then it will be deduced.\n */\n apiBaseUrl: string;\n\n /**\n * The authorization token to use for requests to this provider.\n *\n * If no token is specified, anonymous access is used.\n */\n token?: string;\n\n /**\n * The baseUrl of this provider, e.g. `https://gitlab.com`, which is passed\n * into the GitLab client.\n *\n * If no baseUrl is provided, it will default to `https://${host}`\n */\n baseUrl: string;\n\n /**\n * Signing key to sign commits\n */\n commitSigningKey?: string;\n};\n\n/**\n * Reads a single GitLab integration config.\n *\n * @param config - The config object of a single integration\n * @public\n */\nexport function readGitLabIntegrationConfig(\n config: Config,\n): GitLabIntegrationConfig {\n const host = config.getString('host');\n let apiBaseUrl = config.getOptionalString('apiBaseUrl');\n const token = config.getOptionalString('token')?.trim();\n let baseUrl = config.getOptionalString('baseUrl');\n if (apiBaseUrl) {\n apiBaseUrl = trimEnd(apiBaseUrl, '/');\n } else if (host === GITLAB_HOST) {\n apiBaseUrl = GITLAB_API_BASE_URL;\n }\n\n if (baseUrl) {\n baseUrl = trimEnd(baseUrl, '/');\n } else {\n baseUrl = `https://${host}`;\n }\n\n if (!isValidHost(host)) {\n throw new Error(\n `Invalid GitLab integration config, '${host}' is not a valid host`,\n );\n } else if (!apiBaseUrl || !isValidUrl(apiBaseUrl)) {\n throw new Error(\n `Invalid GitLab integration config, '${apiBaseUrl}' is not a valid apiBaseUrl`,\n );\n } else if (!isValidUrl(baseUrl)) {\n throw new Error(\n `Invalid GitLab integration config, '${baseUrl}' is not a valid baseUrl`,\n );\n }\n\n return {\n host,\n token,\n apiBaseUrl,\n baseUrl,\n commitSigningKey: config.getOptionalString('commitSigningKey'),\n };\n}\n\n/**\n * Reads a set of GitLab integration configs, and inserts some defaults for\n * public GitLab if not specified.\n *\n * @param configs - All of the integration config objects\n * @public\n */\nexport function readGitLabIntegrationConfigs(\n configs: Config[],\n): GitLabIntegrationConfig[] {\n // First read all the explicit integrations\n const result = configs.map(readGitLabIntegrationConfig);\n\n // As a convenience we always make sure there's at least an unauthenticated\n // reader for public gitlab repos.\n if (!result.some(c => c.host === GITLAB_HOST)) {\n result.push({\n host: GITLAB_HOST,\n apiBaseUrl: GITLAB_API_BASE_URL,\n baseUrl: `https://${GITLAB_HOST}`,\n });\n }\n\n return result;\n}\n\n/**\n * Reads a GitLab integration config, and returns\n * relative path.\n *\n * @param config - GitLabIntegrationConfig object\n * @public\n */\nexport function getGitLabIntegrationRelativePath(\n config: GitLabIntegrationConfig,\n): string {\n let relativePath = '';\n if (config.host !== GITLAB_HOST) {\n relativePath = new URL(config.baseUrl).pathname;\n }\n return trimEnd(relativePath, '/');\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 { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport {\n GitLabIntegrationConfig,\n readGitLabIntegrationConfigs,\n} from './config';\n\n/**\n * A GitLab based integration.\n *\n * @public\n */\nexport class GitLabIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<GitLabIntegration> = ({ config }) => {\n const configs = readGitLabIntegrationConfigs(\n config.getOptionalConfigArray('integrations.gitlab') ?? [],\n );\n return basicIntegrations(\n configs.map(c => new GitLabIntegration(c)),\n i => i.config.host,\n );\n };\n\n constructor(private readonly integrationConfig: GitLabIntegrationConfig) {}\n\n get type(): string {\n return 'gitlab';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): GitLabIntegrationConfig {\n return this.integrationConfig;\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n }): string {\n return defaultScmResolveUrl(options);\n }\n\n resolveEditUrl(url: string): string {\n return replaceGitLabUrlType(url, 'edit');\n }\n}\n\n/**\n * Takes a GitLab URL and replaces the type part (blob, tree etc).\n *\n * @param url - The original URL\n * @param type - The desired type, e.g. 'blob', 'tree', 'edit'\n * @public\n */\nexport function replaceGitLabUrlType(\n url: string,\n type: 'blob' | 'tree' | 'edit',\n): string {\n return url.replace(/\\/\\-\\/(blob|tree|edit)\\//, `/-/${type}/`);\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 { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport { GiteaIntegrationConfig, readGiteaConfig } from './config';\nimport { getGiteaEditContentsUrl } from './core';\n\n/**\n * A Gitea based integration.\n *\n * @public\n */\nexport class GiteaIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<GiteaIntegration> = ({ config }) => {\n const configs = config.getOptionalConfigArray('integrations.gitea') ?? [];\n const giteaConfigs = configs.map(c => readGiteaConfig(c));\n\n return basicIntegrations(\n giteaConfigs.map(c => new GiteaIntegration(c)),\n (gitea: GiteaIntegration) => gitea.config.host,\n );\n };\n\n constructor(readonly config: GiteaIntegrationConfig) {}\n\n get type(): string {\n return 'gitea';\n }\n\n get title(): string {\n return this.config.host;\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number | undefined;\n }): string {\n return defaultScmResolveUrl(options);\n }\n\n resolveEditUrl(url: string): string {\n return getGiteaEditContentsUrl(this.config, url);\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 */\n\nimport { Config } from '@backstage/config';\nimport { trimEnd } from 'lodash';\nimport { isValidHost, isValidUrl } from '../helpers';\n\n/**\n * The configuration for a single Gitea integration.\n *\n * @public\n */\nexport type GiteaIntegrationConfig = {\n /**\n * The host of the target that this matches on, e.g. \"gitea.website.com\"\n */\n host: string;\n /**\n * The optional base URL of the Gitea instance. It is assumed that https\n * is used and that the base path is \"/\" on the host. If that is not the\n * case set the complete base url to the gitea instance, e.g.\n * \"https://gitea.website.com/\". This is the url that you would open\n * in a browser.\n */\n baseUrl?: string;\n /**\n * The username to use for requests to gitea.\n */\n username?: string;\n\n /**\n * The password or http token to use for authentication.\n */\n password?: string;\n\n /**\n * Signing key to to sign commits\n */\n commitSigningKey?: string;\n};\n\n/**\n * Parses a location config block for use in GiteaIntegration\n *\n * @public\n */\nexport function readGiteaConfig(config: Config): GiteaIntegrationConfig {\n const host = config.getString('host');\n let baseUrl = config.getOptionalString('baseUrl');\n const username = config.getOptionalString('username');\n const password = config.getOptionalString('password')?.trim();\n\n if (!isValidHost(host)) {\n throw new Error(\n `Invalid Gitea integration config, '${host}' is not a valid host`,\n );\n } else if (baseUrl && !isValidUrl(baseUrl)) {\n throw new Error(\n `Invalid Gitea integration config, '${baseUrl}' is not a valid baseUrl`,\n );\n }\n\n if (baseUrl) {\n baseUrl = trimEnd(baseUrl, '/');\n } else {\n baseUrl = `https://${host}`;\n }\n\n return {\n host,\n baseUrl,\n username,\n password,\n commitSigningKey: config.getOptionalString('commitSigningKey'),\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 { GiteaIntegrationConfig } from './config';\n\n/**\n * Given a URL pointing to a file, returns a URL\n * for editing the contents of the data.\n *\n * @remarks\n *\n * Converts\n * from: https://gitea.com/a/b/src/branchname/path/to/c.yaml\n * or: https://gitea.com/a/b/_edit/branchname/path/to/c.yaml\n *\n * @param url - A URL pointing to a file\n * @param config - The relevant provider config\n * @public\n */\nexport function getGiteaEditContentsUrl(\n config: GiteaIntegrationConfig,\n url: string,\n) {\n const giteaUrl = parseGiteaUrl(config, url);\n return `${giteaUrl.url}/${giteaUrl.owner}/${giteaUrl.name}/_edit/${giteaUrl.ref}/${giteaUrl.path}`;\n}\n\n/**\n * Given a URL pointing to a file, returns an api URL\n * for fetching the contents of the data.\n *\n * @remarks\n *\n * Converts\n * from: https://gitea.com/a/b/src/branch/branchname/path/to/c.yaml\n * to: https://gitea.com/api/v1/repos/a/b/contents/path/to/c.yaml?ref=branchname\n *\n * @param url - A URL pointing to a file\n * @param config - The relevant provider config\n * @public\n */\nexport function getGiteaFileContentsUrl(\n config: GiteaIntegrationConfig,\n url: string,\n) {\n const giteaUrl = parseGiteaUrl(config, url);\n return `${giteaUrl.url}/api/v1/repos/${giteaUrl.owner}/${giteaUrl.name}/contents/${giteaUrl.path}?ref=${giteaUrl.ref}`;\n}\n\n/**\n * Given a URL pointing to a repository/path, returns a URL\n * for archive contents of the repository.\n *\n * @remarks\n *\n * Converts\n * from: https://gitea.com/a/b/src/branchname\n * or: https://gitea.com/api/v1/repos/a/b/archive/branchname.tar.gz\n *\n * @param url - A URL pointing to a repository/path\n * @param config - The relevant provider config\n * @public\n */\nexport function getGiteaArchiveUrl(\n config: GiteaIntegrationConfig,\n url: string,\n) {\n const giteaUrl = parseGiteaUrl(config, url);\n return `${giteaUrl.url}/api/v1/repos/${giteaUrl.owner}/${giteaUrl.name}/archive/${giteaUrl.ref}.tar.gz`;\n}\n\n/**\n * Given a URL pointing to a repository branch, returns a URL\n * for latest commit information.\n *\n * @remarks\n *\n * Converts\n * from: https://gitea.com/a/b/src/branchname\n * or: https://gitea.com/api/v1/repos/a/b/git/commits/branchname\n *\n * @param url - A URL pointing to a repository branch\n * @param config - The relevant provider config\n * @public\n */\nexport function getGiteaLatestCommitUrl(\n config: GiteaIntegrationConfig,\n url: string,\n) {\n const giteaUrl = parseGiteaUrl(config, url);\n return `${giteaUrl.url}/api/v1/repos/${giteaUrl.owner}/${giteaUrl.name}/git/commits/${giteaUrl.ref}`;\n}\n\n/**\n * Return request headers for a Gitea provider.\n *\n * @param config - A Gitea provider config\n * @public\n */\nexport function getGiteaRequestOptions(config: GiteaIntegrationConfig): {\n headers?: Record<string, string>;\n} {\n const headers: Record<string, string> = {};\n const { username, password } = config;\n\n if (!password) {\n return headers;\n }\n\n if (username) {\n headers.Authorization = `basic ${Buffer.from(\n `${username}:${password}`,\n ).toString('base64')}`;\n } else {\n headers.Authorization = `token ${password}`;\n }\n\n return {\n headers,\n };\n}\n\n/**\n * Return parsed git url properties.\n *\n * @param config - A Gitea provider config\n * @param url - A URL pointing to a repository\n * @public\n */\nexport function parseGiteaUrl(\n config: GiteaIntegrationConfig,\n url: string,\n): {\n url: string;\n owner: string;\n name: string;\n ref: string;\n path: string;\n} {\n const baseUrl = config.baseUrl ?? `https://${config.host}`;\n try {\n const [_blank, owner, name, _src, _branch, ref, ...path] = url\n .replace(baseUrl, '')\n .split('/');\n const pathWithoutSlash = path.join('/').replace(/^\\//, '');\n\n return {\n url: baseUrl,\n owner: owner,\n name: name,\n ref: ref,\n path: pathWithoutSlash,\n };\n } catch (e) {\n throw new Error(`Incorrect URL: ${url}, ${e}`);\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 { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport { HarnessIntegrationConfig, readHarnessConfig } from './config';\nimport { getHarnessEditContentsUrl } from './core';\n\n/**\n * A Harness Code based integration.\n *\n * @public\n */\nexport class HarnessIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<HarnessIntegration> = ({ config }) => {\n const configs = config.getOptionalConfigArray('integrations.harness') ?? [];\n const harnessConfigs = configs.map(c => readHarnessConfig(c));\n\n return basicIntegrations(\n harnessConfigs.map(c => new HarnessIntegration(c)),\n (harness: HarnessIntegration) => harness.config.host,\n );\n };\n\n constructor(readonly config: HarnessIntegrationConfig) {}\n\n get type(): string {\n return 'harness';\n }\n\n get title(): string {\n return this.config.host;\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number | undefined;\n }): string {\n return defaultScmResolveUrl(options);\n }\n\n resolveEditUrl(url: string): string {\n return getHarnessEditContentsUrl(this.config, url);\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 { Config } from '@backstage/config';\nimport { isValidHost } from '../helpers';\n\n/**\n * The configuration for a single Harness integration.\n *\n * @public\n */\nexport type HarnessIntegrationConfig = {\n /**\n * The host of the target that this matches on, e.g. \"app.harness.io\"\n */\n host: string;\n /**\n * The password or http token to use for authentication.\n */\n token?: string;\n /**\n * The API key to use for authentication.\n */\n apiKey?: string;\n};\n\n/**\n * Parses a location config block for use in HarnessIntegration\n *\n * @public\n */\nexport function readHarnessConfig(config: Config): HarnessIntegrationConfig {\n const host = config.getString('host');\n const token = config.getOptionalString('token');\n const apiKey = config.getOptionalString('apiKey');\n\n if (!isValidHost(host)) {\n throw new Error(\n `Invalid Harness Code integration config, '${host}' is not a valid host`,\n );\n }\n\n return {\n host,\n apiKey,\n token,\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 { HarnessIntegrationConfig } from './config';\n\n/**\n * Given a URL pointing to a file, returns a URL\n * for editing the contents of the data.\n *\n * @remarks\n *\n * Converts\n * from: https://app.harness.io/a/b/src/branchname/path/to/c.yaml\n * or: https://app.harness.io/a/b/_edit/branchname/path/to/c.yaml\n *\n * @param url - A URL pointing to a file\n * @param config - The relevant provider config\n * @public\n */\nexport function getHarnessEditContentsUrl(\n config: HarnessIntegrationConfig,\n url: string,\n) {\n const parsedUrl = parseHarnessUrl(config, url);\n\n return `${parsedUrl.baseUrl}/ng/account/${parsedUrl.accountId}/module/code${\n parsedUrl.orgName !== '' ? `/orgs/${parsedUrl.orgName}` : ''\n }${\n parsedUrl.projectName !== '' ? `/projects/${parsedUrl.projectName}` : ''\n }/repos/${parsedUrl.repoName}/files/${parsedUrl.branch}/~/${parsedUrl.path}`;\n}\n\n/**\n * Given a file path URL,\n * it returns an API URL which returns the contents of the file .\n * @remarks\n *\n * Converts\n * from: https://app.harness.io/ng/account/accountId/module/code/orgs/orgName/projects/projName/repos/repoName/files/refMain/~/all-apis.yaml\n * https://qa.harness.io/ng/account/bDCAuAjFSJCLFj_0ug3lCg/module/code/orgs/HiteshTest/repos/impoorter/files/main/~/catalog.yaml\n * to: https://app.harness.io/gateway/code/api/v1/repos/accountId/orgName/projName/repoName/+/content/all-apis.yaml?routingId=accountId&include_commit=false&ref=refMain\n *\n * @param url - A URL pointing to a file\n * @param config - The relevant provider config\n * @public\n */\nexport function getHarnessFileContentsUrl(\n config: HarnessIntegrationConfig,\n url: string,\n) {\n const parsedUrl = parseHarnessUrl(config, url);\n\n let constructedUrl = `${parsedUrl.baseUrl}/gateway/code/api/v1/repos/${parsedUrl.accountId}`;\n\n if (parsedUrl.orgName) {\n constructedUrl += `/${parsedUrl.orgName}`;\n }\n\n if (parsedUrl.projectName) {\n constructedUrl += `/${parsedUrl.projectName}`;\n }\n\n constructedUrl += `/${parsedUrl.repoName}/+/raw/${parsedUrl.path}?routingId=${parsedUrl.accountId}&git_ref=refs/heads/${parsedUrl.refString}`;\n\n return constructedUrl;\n}\n\n/**\n * Given a URL pointing to a repository/path, returns a URL\n * for archive contents of the repository.\n *\n * @remarks\n *\n * Converts\n * from: https://qa.harness.io/ng/account/accountId/module/code/orgs/orgId/projects/projectName/repos/repoName/files/branch/~/fileName\n * to: https://qa.harness.io/gateway/code/api/v1/repos/accountId/orgId/projectName/repoName/+/archive/branch.zip?routingId=accountId\n *\n * @param url - A URL pointing to a repository/path\n * @param config - The relevant provider config\n * @public\n */\nexport function getHarnessArchiveUrl(\n config: HarnessIntegrationConfig,\n url: string,\n) {\n const parsedUrl = parseHarnessUrl(config, url);\n\n let constructedUrl = `${parsedUrl.baseUrl}/gateway/code/api/v1/repos/${parsedUrl.accountId}`;\n\n if (parsedUrl.orgName) {\n constructedUrl += `/${parsedUrl.orgName}`;\n }\n\n if (parsedUrl.projectName) {\n constructedUrl += `/${parsedUrl.projectName}`;\n }\n\n constructedUrl += `/${parsedUrl.repoName}/+/archive/${parsedUrl.branch}.zip?routingId=${parsedUrl.accountId}`;\n\n return constructedUrl;\n}\n\n/**\n * Given a URL pointing to a repository branch, returns a URL\n * for latest commit information.\n *\n * @remarks\n *\n * Converts\n * from: https://app.harness.io/ng/account/accountId/module/code/orgs/orgName/projects/projectName/repos/repoName/files/branchName\n * to: https://app.harness.io/gateway/code/api/v1/repos/accountId/orgName/projectName/repoName/+/content?routingId=accountId&include_commit=true&git_ref=refs/heads/branchName\n *\n * @param url - A URL pointing to a repository branch\n * @param config - The relevant provider config\n * @public\n */\nexport function getHarnessLatestCommitUrl(\n config: HarnessIntegrationConfig,\n url: string,\n) {\n const parsedUrl = parseHarnessUrl(config, url);\n\n let constructedUrl = `${parsedUrl.baseUrl}/gateway/code/api/v1/repos/${parsedUrl.accountId}`;\n\n if (parsedUrl.orgName) {\n constructedUrl += `/${parsedUrl.orgName}`;\n }\n\n if (parsedUrl.projectName) {\n constructedUrl += `/${parsedUrl.projectName}`;\n }\n\n constructedUrl += `/${parsedUrl.repoName}/+/content?routingId=${parsedUrl.accountId}&include_commit=true&git_ref=refs/heads/${parsedUrl.branch}`;\n\n return constructedUrl;\n}\n\n/**\n * Return request headers for a Harness Code provider.\n *\n * @param config - A Harness Code provider config\n * @public\n */\nexport function getHarnessRequestOptions(config: HarnessIntegrationConfig): {\n headers?: Record<string, string>;\n} {\n const headers: Record<string, string> = {};\n const { token, apiKey } = config;\n\n if (apiKey) {\n headers['x-api-key'] = apiKey;\n } else if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n return {\n headers,\n };\n}\n\n/**\n * Return parsed git url properties.\n *\n * @param config - A Harness provider config\n * @param url - A URL pointing to a repository\n * @public\n */\nexport function parseHarnessUrl(\n config: HarnessIntegrationConfig,\n url: string,\n): {\n baseUrl: string;\n accountId: string;\n orgName: string;\n projectName: string;\n refString: string;\n repoName: string;\n path: string;\n refDashStr: string;\n branch: string;\n} {\n const baseUrl = `https://${config.host}`;\n try {\n const pathUrl = new URL(url);\n const pathSegments = pathUrl.pathname\n .split('/')\n .filter(segment => segment !== '');\n const urlParts = pathUrl.pathname.split('/');\n\n const accountIdIndex =\n pathSegments.findIndex(segment => segment === 'account') + 1;\n const accountId = pathSegments[accountIdIndex];\n\n const orgNameIndex = pathSegments.findIndex(segment => segment === 'orgs');\n const orgName = orgNameIndex !== -1 ? pathSegments[orgNameIndex + 1] : '';\n const projectNameIndex = pathSegments.findIndex(\n segment => segment === 'projects',\n );\n\n const projectName =\n projectNameIndex !== -1 ? pathSegments[projectNameIndex + 1] : '';\n // Adjust repoNameIndex to correctly identify the repository name\n const repoNameIndex =\n pathSegments.findIndex(\n (segment, index) =>\n segment === 'repos' &&\n index > Math.max(accountIdIndex, orgNameIndex, projectNameIndex),\n ) + 1;\n const repoName = pathSegments[repoNameIndex];\n const refAndPath = urlParts.slice(\n urlParts.findIndex(i => i === 'files' || i === 'edit') + 1,\n );\n const refIndex = refAndPath.findIndex(item => item === '~');\n\n const refString = refAndPath.slice(0, refIndex).join('/');\n const pathWithoutSlash =\n refIndex !== -1\n ? refAndPath\n .slice(refIndex + 1)\n .join('/')\n .replace(/^\\//, '')\n : '';\n\n return {\n baseUrl: baseUrl,\n accountId: accountId,\n orgName: orgName,\n projectName: projectName,\n refString: refString,\n path: pathWithoutSlash,\n repoName: repoName,\n refDashStr: refAndPath.slice(0, refIndex).join('-'),\n branch:\n refIndex !== -1\n ? refAndPath.slice(0, refIndex).join('/')\n : refAndPath.join('/'),\n };\n } catch (e) {\n throw new Error(`Incorrect URL: ${url}, ${e}`);\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 { Config } from '@backstage/config';\n\nconst AZURE_HOST = 'blob.core.windows.net';\n\n/**\n * The configuration parameters for a single Azure Blob Storage account.\n *\n * @public\n */\nexport type AzureBlobStorageIntegrationConfig = {\n /**\n * The name of the Azure Storage Account, e.g., \"mystorageaccount\".\n */\n accountName?: string;\n\n /**\n * The primary or secondary key for the Azure Storage Account.\n * Only required if connectionString or SAS token are not specified.\n */\n accountKey?: string;\n\n /**\n * A Shared Access Signature (SAS) token for limited access to resources.\n */\n sasToken?: string;\n\n /**\n * A full connection string for the Azure Storage Account.\n * This includes the account name, key, and endpoint details.\n */\n connectionString?: string;\n\n /**\n * Optional endpoint suffix for custom domains or sovereign clouds.\n * e.g., \"core.windows.net\" for public Azure or \"core.usgovcloudapi.net\" for US Government cloud.\n */\n endpointSuffix?: string;\n\n /**\n * The host of the target that this matches on, e.g., \"blob.core.windows.net\".\n */\n host: string;\n\n endpoint?: string;\n /**\n * Optional credential to use for Azure Active Directory authentication.\n */\n aadCredential?: {\n /**\n * The client ID of the Azure AD application.\n */\n clientId: string;\n\n /**\n * The tenant ID for Azure AD.\n */\n tenantId: string;\n\n /**\n * The client secret for the Azure AD application.\n */\n clientSecret: string;\n };\n};\n\n/**\n * Reads a single Azure Blob Storage integration config.\n *\n * @param config - The config object of a single integration.\n * @public\n */\nexport function readAzureBlobStorageIntegrationConfig(\n config: Config,\n): AzureBlobStorageIntegrationConfig {\n const endpoint = config.getOptionalString('endpoint');\n const accountName = config.getString('accountName');\n const accountKey = config.getOptionalString('accountKey')?.trim();\n const sasToken = config.getOptionalString('sasToken')?.trim();\n const connectionString = config.getOptionalString('connectionString')?.trim();\n const endpointSuffix = config.getOptionalString('endpointSuffix')?.trim();\n\n let host;\n let pathname;\n if (endpoint) {\n try {\n const url = new URL(endpoint);\n host = url.host;\n pathname = url.pathname;\n } catch {\n throw new Error(\n `invalid azureBlobStorage integration config, endpoint '${endpoint}' is not a valid URL`,\n );\n }\n if (pathname !== '/') {\n throw new Error(\n `invalid azureBlobStorage integration config, endpoints cannot contain path, got '${endpoint}'`,\n );\n }\n } else {\n host = AZURE_HOST;\n }\n const aadCredential = config.has('aadCredential')\n ? {\n clientId: config.getString('aadCredential.clientId'),\n tenantId: config.getString('aadCredential.tenantId'),\n clientSecret: config.getString('aadCredential.clientSecret')?.trim(),\n }\n : undefined;\n\n if (accountKey && sasToken) {\n throw new Error(\n `Invalid Azure Blob Storage config for ${accountName}: Both account key and SAS token cannot be used simultaneously.`,\n );\n }\n\n if (aadCredential && (accountKey || sasToken)) {\n throw new Error(\n `Invalid Azure Blob Storage config for ${accountName}: Cannot use both Azure AD credentials and account keys/SAS tokens for the same account.`,\n );\n }\n\n return {\n host,\n endpoint,\n accountName,\n accountKey,\n sasToken,\n connectionString,\n endpointSuffix,\n aadCredential,\n };\n}\n\n/**\n * Reads a set of Azure Blob Storage integration configs.\n *\n * @param configs - All of the integration config objects.\n * @public\n */\nexport function readAzureBlobStorageIntegrationConfigs(\n configs: Config[],\n): AzureBlobStorageIntegrationConfig[] {\n // First read all the explicit integrations\n const result = configs.map(readAzureBlobStorageIntegrationConfig);\n\n // If no explicit blob.core.windows.net integration was added, put one in the list as\n // a convenience\n if (!result.some(c => c.host === AZURE_HOST)) {\n result.push({\n host: AZURE_HOST,\n });\n }\n return result;\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 { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport { ScmIntegration, ScmIntegrationsFactory } from '../types';\nimport {\n AzureBlobStorageIntegrationConfig,\n readAzureBlobStorageIntegrationConfigs,\n} from './config';\n\n/**\n * Microsoft Azure Blob storage based integration.\n *\n * @public\n */\nexport class AzureBlobStorageIntergation implements ScmIntegration {\n static factory: ScmIntegrationsFactory<AzureBlobStorageIntergation> = ({\n config,\n }) => {\n const configs = readAzureBlobStorageIntegrationConfigs(\n config.getOptionalConfigArray('integrations.azureBlobStorage') ?? [],\n );\n return basicIntegrations(\n configs.map(c => new AzureBlobStorageIntergation(c)),\n i => i.config.host,\n );\n };\n\n get type(): string {\n return 'azureBlobStorage';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): AzureBlobStorageIntegrationConfig {\n return this.integrationConfig;\n }\n\n constructor(\n private readonly integrationConfig: AzureBlobStorageIntegrationConfig,\n ) {}\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number | undefined;\n }): string {\n const resolved = defaultScmResolveUrl(options);\n return resolved;\n }\n\n resolveEditUrl(url: string): string {\n // TODO: Implement edit URL for azureBlobStorage\n return url;\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 { Config } from '@backstage/config';\nimport { AwsS3Integration } from './awsS3/AwsS3Integration';\nimport { AwsCodeCommitIntegration } from './awsCodeCommit/AwsCodeCommitIntegration';\nimport { AzureIntegration } from './azure/AzureIntegration';\nimport { BitbucketCloudIntegration } from './bitbucketCloud/BitbucketCloudIntegration';\nimport { BitbucketIntegration } from './bitbucket/BitbucketIntegration';\nimport { BitbucketServerIntegration } from './bitbucketServer/BitbucketServerIntegration';\nimport { GerritIntegration } from './gerrit/GerritIntegration';\nimport { GithubIntegration } from './github/GithubIntegration';\nimport { GitLabIntegration } from './gitlab/GitLabIntegration';\nimport { defaultScmResolveUrl } from './helpers';\nimport { ScmIntegration, ScmIntegrationsGroup } from './types';\nimport { ScmIntegrationRegistry } from './registry';\nimport { GiteaIntegration } from './gitea';\nimport { HarnessIntegration } from './harness/HarnessIntegration';\nimport { AzureBlobStorageIntergation } from './azureBlobStorage';\n\n/**\n * The set of supported integrations.\n *\n * @public\n */\nexport interface IntegrationsByType {\n awsS3: ScmIntegrationsGroup<AwsS3Integration>;\n awsCodeCommit: ScmIntegrationsGroup<AwsCodeCommitIntegration>;\n azureBlobStorage: ScmIntegrationsGroup<AzureBlobStorageIntergation>;\n azure: ScmIntegrationsGroup<AzureIntegration>;\n /**\n * @deprecated in favor of `bitbucketCloud` and `bitbucketServer`\n */\n bitbucket: ScmIntegrationsGroup<BitbucketIntegration>;\n bitbucketCloud: ScmIntegrationsGroup<BitbucketCloudIntegration>;\n bitbucketServer: ScmIntegrationsGroup<BitbucketServerIntegration>;\n gerrit: ScmIntegrationsGroup<GerritIntegration>;\n github: ScmIntegrationsGroup<GithubIntegration>;\n gitlab: ScmIntegrationsGroup<GitLabIntegration>;\n gitea: ScmIntegrationsGroup<GiteaIntegration>;\n harness: ScmIntegrationsGroup<HarnessIntegration>;\n}\n\n/**\n * Exposes the set of supported integrations.\n *\n * @public\n */\nexport class ScmIntegrations implements ScmIntegrationRegistry {\n private readonly byType: IntegrationsByType;\n\n static fromConfig(config: Config): ScmIntegrations {\n return new ScmIntegrations({\n awsS3: AwsS3Integration.factory({ config }),\n awsCodeCommit: AwsCodeCommitIntegration.factory({ config }),\n azureBlobStorage: AzureBlobStorageIntergation.factory({ config }),\n azure: AzureIntegration.factory({ config }),\n bitbucket: BitbucketIntegration.factory({ config }),\n bitbucketCloud: BitbucketCloudIntegration.factory({ config }),\n bitbucketServer: BitbucketServerIntegration.factory({ config }),\n gerrit: GerritIntegration.factory({ config }),\n github: GithubIntegration.factory({ config }),\n gitlab: GitLabIntegration.factory({ config }),\n gitea: GiteaIntegration.factory({ config }),\n harness: HarnessIntegration.factory({ config }),\n });\n }\n\n constructor(integrationsByType: IntegrationsByType) {\n this.byType = integrationsByType;\n }\n\n get awsS3(): ScmIntegrationsGroup<AwsS3Integration> {\n return this.byType.awsS3;\n }\n\n get awsCodeCommit(): ScmIntegrationsGroup<AwsCodeCommitIntegration> {\n return this.byType.awsCodeCommit;\n }\n\n get azureBlobStorage(): ScmIntegrationsGroup<AzureBlobStorageIntergation> {\n return this.byType.azureBlobStorage;\n }\n\n get azure(): ScmIntegrationsGroup<AzureIntegration> {\n return this.byType.azure;\n }\n\n /**\n * @deprecated in favor of `bitbucketCloud()` and `bitbucketServer()`\n */\n get bitbucket(): ScmIntegrationsGroup<BitbucketIntegration> {\n return this.byType.bitbucket;\n }\n\n get bitbucketCloud(): ScmIntegrationsGroup<BitbucketCloudIntegration> {\n return this.byType.bitbucketCloud;\n }\n\n get bitbucketServer(): ScmIntegrationsGroup<BitbucketServerIntegration> {\n return this.byType.bitbucketServer;\n }\n\n get gerrit(): ScmIntegrationsGroup<GerritIntegration> {\n return this.byType.gerrit;\n }\n\n get github(): ScmIntegrationsGroup<GithubIntegration> {\n return this.byType.github;\n }\n\n get gitlab(): ScmIntegrationsGroup<GitLabIntegration> {\n return this.byType.gitlab;\n }\n\n get gitea(): ScmIntegrationsGroup<GiteaIntegration> {\n return this.byType.gitea;\n }\n\n get harness(): ScmIntegrationsGroup<HarnessIntegration> {\n return this.byType.harness;\n }\n\n list(): ScmIntegration[] {\n return Object.values(this.byType).flatMap(\n i => i.list() as ScmIntegration[],\n );\n }\n\n byUrl(url: string | URL): ScmIntegration | undefined {\n let candidates = Object.values(this.byType)\n .map(i => i.byUrl(url))\n .filter(Boolean);\n\n // Do not return deprecated integrations if there are other options\n if (candidates.length > 1) {\n const filteredCandidates = candidates.filter(\n x => !(x instanceof BitbucketIntegration),\n );\n if (filteredCandidates.length !== 0) {\n candidates = filteredCandidates;\n }\n }\n\n return candidates[0];\n }\n\n byHost(host: string): ScmIntegration | undefined {\n return Object.values(this.byType)\n .map(i => i.byHost(host))\n .find(Boolean);\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n }): string {\n const integration = this.byUrl(options.base);\n if (!integration) {\n return defaultScmResolveUrl(options);\n }\n\n return integration.resolveUrl(options);\n }\n\n resolveEditUrl(url: string): string {\n const integration = this.byUrl(url);\n if (!integration) {\n return url;\n }\n\n return integration.resolveEditUrl(url);\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';\nimport {\n ScmIntegrationRegistry,\n ScmIntegrations,\n} from '@backstage/integration';\nimport { ApiRef, createApiRef } from '@backstage/core-plugin-api';\n\n/**\n * Factory class for creating {@link @backstage/integration#ScmIntegrationRegistry} instances.\n *\n * @public\n */\nexport class ScmIntegrationsApi {\n /**\n * Instantiates an {@link @backstage/integration#ScmIntegrationRegistry}.\n *\n * @param config - The root of the config hierarchy.\n */\n static fromConfig(config: Config): ScmIntegrationRegistry {\n return ScmIntegrations.fromConfig(config);\n }\n}\n\n/**\n * The API that holds all configured SCM integrations.\n *\n * @public\n */\nexport const scmIntegrationsApiRef: ApiRef<ScmIntegrationRegistry> =\n createApiRef({\n id: 'integration.scmintegrations',\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 { Config } from '@backstage/config';\nimport { trimEnd } from 'lodash';\nimport { isValidHost } from '../helpers';\n\nconst GITHUB_HOST = 'github.com';\nconst GITHUB_API_BASE_URL = 'https://api.github.com';\nconst GITHUB_RAW_BASE_URL = 'https://raw.githubusercontent.com';\n\n/**\n * The configuration parameters for a single GitHub integration.\n *\n * @public\n */\nexport type GithubIntegrationConfig = {\n /**\n * The host of the target that this matches on, e.g. \"github.com\"\n */\n host: string;\n\n /**\n * The base URL of the API of this provider, e.g. \"https://api.github.com\",\n * with no trailing slash.\n *\n * May be omitted specifically for GitHub; then it will be deduced.\n *\n * The API will always be preferred if both its base URL and a token are\n * present.\n */\n apiBaseUrl?: string;\n\n /**\n * The base URL of the raw fetch endpoint of this provider, e.g.\n * \"https://raw.githubusercontent.com\", with no trailing slash.\n *\n * May be omitted specifically for GitHub; then it will be deduced.\n *\n * The API will always be preferred if both its base URL and a token are\n * present.\n */\n rawBaseUrl?: string;\n\n /**\n * The authorization token to use for requests to this provider.\n *\n * If no token is specified, anonymous access is used.\n */\n token?: string;\n\n /**\n * The GitHub Apps configuration to use for requests to this provider.\n *\n * If no apps are specified, token or anonymous is used.\n */\n apps?: GithubAppConfig[];\n};\n\n/**\n * The configuration parameters for authenticating a GitHub Application.\n *\n * @remarks\n *\n * A GitHub Apps configuration can be generated using the `backstage-cli create-github-app` command.\n *\n * @public\n */\nexport type GithubAppConfig = {\n /**\n * Unique app identifier, found at https://github.com/organizations/$org/settings/apps/$AppName\n */\n appId: number;\n /**\n * The private key is used by the GitHub App integration to authenticate the app.\n * A private key can be generated from the app at https://github.com/organizations/$org/settings/apps/$AppName\n */\n privateKey: string;\n /**\n * Webhook secret can be configured at https://github.com/organizations/$org/settings/apps/$AppName\n */\n webhookSecret?: string;\n /**\n * Found at https://github.com/organizations/$org/settings/apps/$AppName\n */\n clientId: string;\n /**\n * Client secrets can be generated at https://github.com/organizations/$org/settings/apps/$AppName\n */\n clientSecret: string;\n /**\n * List of installation owners allowed to be used by this GitHub app. The GitHub UI does not provide a way to list the installations.\n * However you can list the installations with the GitHub API. You can find the list of installations here:\n * https://api.github.com/app/installations\n * The relevant documentation for this is here.\n * https://docs.github.com/en/rest/reference/apps#list-installations-for-the-authenticated-app--code-samples\n */\n allowedInstallationOwners?: string[];\n};\n\n/**\n * Reads a single GitHub integration config.\n *\n * @param config - The config object of a single integration\n * @public\n */\nexport function readGithubIntegrationConfig(\n config: Config,\n): GithubIntegrationConfig {\n const host = config.getOptionalString('host') ?? GITHUB_HOST;\n let apiBaseUrl = config.getOptionalString('apiBaseUrl');\n let rawBaseUrl = config.getOptionalString('rawBaseUrl');\n const token = config.getOptionalString('token')?.trim();\n const apps = config.getOptionalConfigArray('apps')?.map(c => ({\n appId: c.getNumber('appId'),\n clientId: c.getString('clientId'),\n clientSecret: c.getString('clientSecret'),\n webhookSecret: c.getOptionalString('webhookSecret'),\n privateKey: c.getString('privateKey'),\n allowedInstallationOwners: c.getOptionalStringArray(\n 'allowedInstallationOwners',\n ),\n }));\n\n if (!isValidHost(host)) {\n throw new Error(\n `Invalid GitHub integration config, '${host}' is not a valid host`,\n );\n }\n\n if (apiBaseUrl) {\n apiBaseUrl = trimEnd(apiBaseUrl, '/');\n } else if (host === GITHUB_HOST) {\n apiBaseUrl = GITHUB_API_BASE_URL;\n }\n\n if (rawBaseUrl) {\n rawBaseUrl = trimEnd(rawBaseUrl, '/');\n } else if (host === GITHUB_HOST) {\n rawBaseUrl = GITHUB_RAW_BASE_URL;\n }\n\n return { host, apiBaseUrl, rawBaseUrl, token, apps };\n}\n\n/**\n * Reads a set of GitHub integration configs, and inserts some defaults for\n * public GitHub if not specified.\n *\n * @param configs - All of the integration config objects\n * @public\n */\nexport function readGithubIntegrationConfigs(\n configs: Config[],\n): GithubIntegrationConfig[] {\n // First read all the explicit integrations\n const result = configs.map(readGithubIntegrationConfig);\n\n // If no explicit github.com integration was added, put one in the list as\n // a convenience\n if (!result.some(c => c.host === GITHUB_HOST)) {\n result.push({\n host: GITHUB_HOST,\n apiBaseUrl: GITHUB_API_BASE_URL,\n rawBaseUrl: GITHUB_RAW_BASE_URL,\n });\n }\n\n return result;\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 { basicIntegrations, defaultScmResolveUrl } from '../helpers';\nimport {\n RateLimitInfo,\n ScmIntegration,\n ScmIntegrationsFactory,\n} from '../types';\nimport {\n GithubIntegrationConfig,\n readGithubIntegrationConfigs,\n} from './config';\nimport { ConsumedResponse } from '@backstage/errors';\n\n/**\n * A GitHub based integration.\n *\n * @public\n */\nexport class GithubIntegration implements ScmIntegration {\n static factory: ScmIntegrationsFactory<GithubIntegration> = ({ config }) => {\n const configs = readGithubIntegrationConfigs(\n config.getOptionalConfigArray('integrations.github') ?? [],\n );\n return basicIntegrations(\n configs.map(c => new GithubIntegration(c)),\n i => i.config.host,\n );\n };\n\n constructor(private readonly integrationConfig: GithubIntegrationConfig) {}\n\n get type(): string {\n return 'github';\n }\n\n get title(): string {\n return this.integrationConfig.host;\n }\n\n get config(): GithubIntegrationConfig {\n return this.integrationConfig;\n }\n\n resolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n }): string {\n // GitHub uses blob URLs for files and tree urls for directory listings. But\n // there is a redirect from tree to blob for files, so we can always return\n // tree urls here.\n return replaceGithubUrlType(defaultScmResolveUrl(options), 'tree');\n }\n\n resolveEditUrl(url: string): string {\n return replaceGithubUrlType(url, 'edit');\n }\n\n parseRateLimitInfo(response: ConsumedResponse): RateLimitInfo {\n return {\n isRateLimited:\n response.status === 429 ||\n (response.status === 403 &&\n response.headers.get('x-ratelimit-remaining') === '0'),\n };\n }\n}\n\n/**\n * Takes a GitHub URL and replaces the type part (blob, tree etc).\n *\n * @param url - The original URL\n * @param type - The desired type, e.g. \"blob\"\n * @public\n */\nexport function replaceGithubUrlType(\n url: string,\n type: 'blob' | 'tree' | 'edit',\n): string {\n return url.replace(\n /\\/\\/([^/]+)\\/([^/]+)\\/([^/]+)\\/(blob|tree|edit)\\//,\n (_, host, owner, repo) => {\n return `//${host}/${owner}/${repo}/${type}/`;\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 parseGitUrl from 'git-url-parse';\nimport { trimEnd } from 'lodash';\nimport { ScmIntegration, ScmIntegrationsGroup } from './types';\n\n/** Checks whether the given argument is a valid URL hostname */\nexport function isValidHost(host: string): boolean {\n const check = new URL('http://example.com');\n check.host = host;\n return check.host === host;\n}\n\n/** Checks whether the given argument is a valid URL */\nexport function isValidUrl(url: string): boolean {\n try {\n // eslint-disable-next-line no-new\n new URL(url);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function basicIntegrations<T extends ScmIntegration>(\n integrations: T[],\n getHost: (integration: T) => string,\n): ScmIntegrationsGroup<T> {\n return {\n list(): T[] {\n return integrations;\n },\n byUrl(url: string | URL): T | undefined {\n try {\n const parsed = typeof url === 'string' ? new URL(url) : url;\n return integrations.find(i => getHost(i) === parsed.host);\n } catch {\n return undefined;\n }\n },\n byHost(host: string): T | undefined {\n return integrations.find(i => getHost(i) === host);\n },\n };\n}\n\n/**\n * Default implementation of {@link ScmIntegration} `resolveUrl`, that only\n * works with URL pathname based providers.\n *\n * @public\n */\nexport function defaultScmResolveUrl(options: {\n url: string;\n base: string;\n lineNumber?: number;\n}): string {\n const { url, base, lineNumber } = options;\n\n // If it is a fully qualified URL - then return it verbatim\n try {\n // eslint-disable-next-line no-new\n new URL(url);\n return url;\n } catch {\n // ignore intentionally\n }\n\n let updated: URL;\n\n if (url.startsWith('/')) {\n // If it is an absolute path, move relative to the repo root\n const { href, filepath } = parseGitUrl(base);\n\n updated = new URL(href);\n\n const repoRootPath = trimEnd(\n updated.pathname.substring(0, updated.pathname.length - filepath.length),\n '/',\n );\n updated.pathname = `${repoRootPath}${url}`;\n } else {\n // For relative URLs, just let the default URL constructor handle the\n // resolving. Note that this essentially will treat the last segment of the\n // base as a file - NOT a folder - unless the url ends in a slash.\n updated = new URL(url, base);\n }\n\n updated.search = new URL(base).search;\n if (lineNumber) {\n updated.hash = `L${lineNumber}`;\n }\n return updated.toString();\n}\n\n/**\n * Sets up handlers for request mocking\n *\n * Copied from test-utils, as that is a frontend-only package\n *\n * @param worker - service worker\n */\nexport function registerMswTestHooks(worker: {\n listen: (t: any) => void;\n close: () => void;\n resetHandlers: () => void;\n}) {\n beforeAll(() => worker.listen({ onUnhandledRequest: 'error' }));\n afterAll(() => worker.close());\n afterEach(() => worker.resetHandlers());\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 { apis, components, icons, themes } from './defaults';\nimport {\n AppTheme,\n BackstagePlugin,\n IconComponent,\n} from '@backstage/core-plugin-api';\nimport {\n AppComponents,\n AppOptions,\n AppIcons,\n createSpecializedApp,\n} from '@backstage/core-app-api';\n\n/**\n * Creates a new Backstage App using a default set of components, icons and themes unless\n * they are explicitly provided.\n *\n * @public\n */\nexport function createApp(\n options?: Omit<AppOptions, keyof OptionalAppOptions> & OptionalAppOptions,\n) {\n return createSpecializedApp({\n ...options,\n apis: options?.apis ?? [],\n bindRoutes: options?.bindRoutes,\n components: {\n ...components,\n ...options?.components,\n },\n configLoader: options?.configLoader,\n defaultApis: apis,\n icons: {\n ...icons,\n ...options?.icons,\n },\n plugins: (options?.plugins as BackstagePlugin[]) ?? [],\n featureFlags: options?.featureFlags ?? [],\n themes: options?.themes ?? themes,\n });\n}\n\n/**\n * The set of app options that {@link createApp} will provide defaults for\n * if they are not passed in explicitly.\n *\n * @public\n */\nexport type OptionalAppOptions = {\n /**\n * A set of icons to override the default icons with.\n *\n * The override is applied for each icon individually.\n *\n * @public\n */\n icons?: Partial<AppIcons> & {\n [key in string]: IconComponent;\n };\n\n /**\n * A set of themes that override all of the default app themes.\n *\n * If this option is provided none of the default themes will be used.\n *\n * @public\n */\n themes?: (Partial<AppTheme> & Omit<AppTheme, 'theme'>)[]; // TODO: simplify once AppTheme is updated\n\n /**\n * A set of components to override the default components with.\n *\n * The override is applied for each app component individually.\n *\n * @public\n */\n components?: Partial<AppComponents>;\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 { ApiRef, createApiRef } from '../system';\nimport { IconComponent } from '../../icons/types';\nimport { Observable } from '@backstage/types';\n\n/**\n * This file contains declarations for common interfaces of auth-related APIs.\n * The declarations should be used to signal which type of authentication and\n * authorization methods each separate auth provider supports.\n *\n * For example, a Google OAuth provider that supports OAuth 2 and OpenID Connect,\n * would be declared as follows:\n *\n * const googleAuthApiRef = createApiRef<OAuthApi & OpenIDConnectApi>({ ... })\n */\n\n/**\n * Information about the auth provider.\n *\n * @remarks\n *\n * This information is used both to connect the correct auth provider in the backend, as\n * well as displaying the provider to the user.\n *\n * @public\n */\nexport type AuthProviderInfo = {\n /**\n * The ID of the auth provider. This should match with ID of the provider in the `@backstage/auth-backend`.\n */\n id: string;\n\n /**\n * Title for the auth provider, for example \"GitHub\"\n */\n title: string;\n\n /**\n * Icon for the auth provider.\n */\n icon: IconComponent;\n\n /**\n * Optional user friendly messaage to display for the auth provider.\n */\n message?: string;\n};\n\n/**\n * An array of scopes, or a scope string formatted according to the\n * auth provider, which is typically a space separated list.\n *\n * @remarks\n *\n * See the documentation for each auth provider for the list of scopes\n * supported by each provider.\n *\n * @public\n */\nexport type OAuthScope = string | string[];\n\n/**\n * Configuration of an authentication request.\n *\n * @public\n */\nexport type AuthRequestOptions = {\n /**\n * If this is set to true, the user will not be prompted to log in,\n * and an empty response will be returned if there is no existing session.\n *\n * This can be used to perform a check whether the user is logged in, or if you don't\n * want to force a user to be logged in, but provide functionality if they already are.\n *\n * @defaultValue false\n */\n optional?: boolean;\n\n /**\n * If this is set to true, the request will bypass the regular oauth login modal\n * and open the login popup directly.\n *\n * The method must be called synchronously from a user action for this to work in all browsers.\n *\n * @defaultValue false\n */\n instantPopup?: boolean;\n};\n\n/**\n * This API provides access to OAuth 2 credentials. It lets you request access tokens,\n * which can be used to act on behalf of the user when talking to APIs.\n *\n * @public\n */\nexport type OAuthApi = {\n /**\n * Requests an OAuth 2 Access Token, optionally with a set of scopes. The access token allows\n * you to make requests on behalf of the user, and the copes may grant you broader access, depending\n * on the auth provider.\n *\n * Each auth provider has separate handling of scope, so you need to look at the documentation\n * for each one to know what scope you need to request.\n *\n * This method is cheap and should be called each time an access token is used. Do not for example\n * store the access token in React component state, as that could cause the token to expire. Instead\n * fetch a new access token for each request.\n *\n * Be sure to include all required scopes when requesting an access token. When testing your implementation\n * it is best to log out the Backstage session and then visit your plugin page directly, as\n * you might already have some required scopes in your existing session. Not requesting the correct\n * scopes can lead to 403 or other authorization errors, which can be tricky to debug.\n *\n * If the user has not yet granted access to the provider and the set of requested scopes, the user\n * will be prompted to log in. The returned promise will not resolve until the user has\n * successfully logged in. The returned promise can be rejected, but only if the user rejects the login request.\n */\n getAccessToken(\n scope?: OAuthScope,\n options?: AuthRequestOptions,\n ): Promise<string>;\n};\n\n/**\n * This API provides access to OpenID Connect credentials. It lets you request ID tokens,\n * which can be passed to backend services to prove the user's identity.\n *\n * @public\n */\nexport type OpenIdConnectApi = {\n /**\n * Requests an OpenID Connect ID Token.\n *\n * This method is cheap and should be called each time an ID token is used. Do not for example\n * store the id token in React component state, as that could cause the token to expire. Instead\n * fetch a new id token for each request.\n *\n * If the user has not yet logged in to Google inside Backstage, the user will be prompted\n * to log in. The returned promise will not resolve until the user has successfully logged in.\n * The returned promise can be rejected, but only if the user rejects the login request.\n */\n getIdToken(options?: AuthRequestOptions): Promise<string>;\n};\n\n/**\n * This API provides access to profile information of the user from an auth provider.\n *\n * @public\n */\nexport type ProfileInfoApi = {\n /**\n * Get profile information for the user as supplied by this auth provider.\n *\n * If the optional flag is not set, a session is guaranteed to be returned, while if\n * the optional flag is set, the session may be undefined. See {@link AuthRequestOptions} for more details.\n */\n getProfile(options?: AuthRequestOptions): Promise<ProfileInfo | undefined>;\n};\n\n/**\n * This API provides access to the user's identity within Backstage.\n *\n * @remarks\n *\n * An auth provider that implements this interface can be used to sign-in to backstage. It is\n * not intended to be used directly from a plugin, but instead serves as a connection between\n * this authentication method and the app's {@link IdentityApi}\n *\n * @public\n */\nexport type BackstageIdentityApi = {\n /**\n * Get the user's identity within Backstage. This should normally not be called directly,\n * use the {@link IdentityApi} instead.\n *\n * If the optional flag is not set, a session is guaranteed to be returned, while if\n * the optional flag is set, the session may be undefined. See {@link AuthRequestOptions} for more details.\n */\n getBackstageIdentity(\n options?: AuthRequestOptions,\n ): Promise<BackstageIdentityResponse | undefined>;\n};\n\n/**\n * User identity information within Backstage.\n *\n * @public\n */\nexport type BackstageUserIdentity = {\n /**\n * The type of identity that this structure represents. In the frontend app\n * this will currently always be 'user'.\n */\n type: 'user';\n\n /**\n * The entityRef of the user in the catalog.\n * For example User:default/sandra\n */\n userEntityRef: string;\n\n /**\n * The user and group entities that the user claims ownership through\n */\n ownershipEntityRefs: string[];\n};\n\n/**\n * Token and Identity response, with the users claims in the Identity.\n *\n * @public\n */\nexport type BackstageIdentityResponse = {\n /**\n * The token used to authenticate the user within Backstage.\n */\n token: string;\n\n /**\n * The time at which the token expires. If not set, it can be assumed that the token does not expire.\n */\n expiresAt?: Date;\n\n /**\n * Identity information derived from the token.\n */\n identity: BackstageUserIdentity;\n};\n\n/**\n * Profile information of the user.\n *\n * @public\n */\nexport type ProfileInfo = {\n /**\n * Email ID.\n */\n email?: string;\n\n /**\n * Display name that can be presented to the user.\n */\n displayName?: string;\n\n /**\n * URL to an avatar image of the user.\n */\n picture?: string;\n};\n\n/**\n * Session state values passed to subscribers of the SessionApi.\n *\n * @public\n */\nexport enum SessionState {\n /**\n * User signed in.\n */\n SignedIn = 'SignedIn',\n /**\n * User not signed in.\n */\n SignedOut = 'SignedOut',\n}\n\n/**\n * The SessionApi provides basic controls for any auth provider that is tied to a persistent session.\n *\n * @public\n */\nexport type SessionApi = {\n /**\n * Sign in with a minimum set of permissions.\n */\n signIn(): Promise<void>;\n\n /**\n * Sign out from the current session. This will reload the page.\n */\n signOut(): Promise<void>;\n\n /**\n * Observe the current state of the auth session. Emits the current state on subscription.\n */\n sessionState$(): Observable<SessionState>;\n};\n\n/**\n * Provides authentication towards Google APIs and identities.\n *\n * @public\n * @remarks\n *\n * See {@link https://developers.google.com/identity/protocols/googlescopes} for a full list of supported scopes.\n *\n * Note that the ID token payload is only guaranteed to contain the user's numerical Google ID,\n * email and expiration information. Do not rely on any other fields, as they might not be present.\n */\nexport const googleAuthApiRef: ApiRef<\n OAuthApi &\n OpenIdConnectApi &\n ProfileInfoApi &\n BackstageIdentityApi &\n SessionApi\n> = createApiRef({\n id: 'core.auth.google',\n});\n\n/**\n * Provides authentication towards GitHub APIs.\n *\n * @public\n * @remarks\n *\n * See {@link https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/}\n * for a full list of supported scopes.\n */\nexport const githubAuthApiRef: ApiRef<\n OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi\n> = createApiRef({\n id: 'core.auth.github',\n});\n\n/**\n * Provides authentication towards Okta APIs.\n *\n * @public\n * @remarks\n *\n * See {@link https://developer.okta.com/docs/guides/implement-oauth-for-okta/scopes/}\n * for a full list of supported scopes.\n */\nexport const oktaAuthApiRef: ApiRef<\n OAuthApi &\n OpenIdConnectApi &\n ProfileInfoApi &\n BackstageIdentityApi &\n SessionApi\n> = createApiRef({\n id: 'core.auth.okta',\n});\n\n/**\n * Provides authentication towards GitLab APIs.\n *\n * @public\n * @remarks\n *\n * See {@link https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#limiting-scopes-of-a-personal-access-token}\n * for a full list of supported scopes.\n */\nexport const gitlabAuthApiRef: ApiRef<\n OAuthApi &\n OpenIdConnectApi &\n ProfileInfoApi &\n BackstageIdentityApi &\n SessionApi\n> = createApiRef({\n id: 'core.auth.gitlab',\n});\n\n/**\n * Provides authentication towards Microsoft APIs and identities.\n *\n * @public\n * @remarks\n *\n * For more info and a full list of supported scopes, see:\n * - {@link https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent}\n * - {@link https://docs.microsoft.com/en-us/graph/permissions-reference}\n */\nexport const microsoftAuthApiRef: ApiRef<\n OAuthApi &\n OpenIdConnectApi &\n ProfileInfoApi &\n BackstageIdentityApi &\n SessionApi\n> = createApiRef({\n id: 'core.auth.microsoft',\n});\n\n/**\n * Provides authentication towards OneLogin APIs.\n *\n * @public\n */\nexport const oneloginAuthApiRef: ApiRef<\n OAuthApi &\n OpenIdConnectApi &\n ProfileInfoApi &\n BackstageIdentityApi &\n SessionApi\n> = createApiRef({\n id: 'core.auth.onelogin',\n});\n\n/**\n * Provides authentication towards Bitbucket APIs.\n *\n * @public\n * @remarks\n *\n * See {@link https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/}\n * for a full list of supported scopes.\n */\nexport const bitbucketAuthApiRef: ApiRef<\n OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi\n> = createApiRef({\n id: 'core.auth.bitbucket',\n});\n\n/**\n * Provides authentication towards Bitbucket Server APIs.\n *\n * @public\n * @remarks\n *\n * See {@link https://confluence.atlassian.com/bitbucketserver/bitbucket-oauth-2-0-provider-api-1108483661.html#BitbucketOAuth2.0providerAPI-scopes}\n * for a full list of supported scopes.\n */\nexport const bitbucketServerAuthApiRef: ApiRef<\n OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi\n> = createApiRef({\n id: 'core.auth.bitbucket-server',\n});\n\n/**\n * Provides authentication towards Atlassian APIs.\n *\n * @public\n * @remarks\n *\n * See {@link https://developer.atlassian.com/cloud/jira/platform/scopes-for-connect-and-oauth-2-3LO-apps/}\n * for a full list of supported scopes.\n */\nexport const atlassianAuthApiRef: ApiRef<\n OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi\n> = createApiRef({\n id: 'core.auth.atlassian',\n});\n\n/**\n * Provides authentication towards VMware Cloud APIs and identities.\n *\n * @public\n * @remarks\n *\n * For more info about VMware Cloud identity and access management:\n * - {@link https://docs.vmware.com/en/VMware-Cloud-services/services/Using-VMware-Cloud-Services/GUID-53D39337-D93A-4B84-BD18-DDF43C21479A.html}\n */\nexport const vmwareCloudAuthApiRef: ApiRef<\n OAuthApi &\n OpenIdConnectApi &\n ProfileInfoApi &\n BackstageIdentityApi &\n SessionApi\n> = createApiRef({\n id: 'core.auth.vmware-cloud',\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 { ApiFactoryHolder } from './types';\nimport {\n ApiRef,\n ApiFactory,\n AnyApiRef,\n AnyApiFactory,\n} from '@backstage/core-plugin-api';\n\n/**\n * Scope type when registering API factories.\n * @public\n */\nexport type ApiFactoryScope =\n | 'default' // Default factories registered by core and plugins\n | 'app' // Factories registered in the app, overriding default ones\n | 'static'; // APIs that can't be overridden, e.g. config\n\nenum ScopePriority {\n default = 10,\n app = 50,\n static = 100,\n}\n\ntype FactoryTuple = {\n priority: number;\n factory: AnyApiFactory;\n};\n\n/**\n * ApiFactoryRegistry is an ApiFactoryHolder implementation that enables\n * registration of API Factories with different scope.\n *\n * Each scope has an assigned priority, where factories registered with\n * higher priority scopes override ones with lower priority.\n *\n * @public\n */\nexport class ApiFactoryRegistry implements ApiFactoryHolder {\n private readonly factories = new Map<string, FactoryTuple>();\n\n /**\n * Register a new API factory. Returns true if the factory was added\n * to the registry.\n *\n * A factory will not be added to the registry if there is already\n * an existing factory with the same or higher priority.\n */\n register<Api, Impl extends Api, Deps extends { [name in string]: unknown }>(\n scope: ApiFactoryScope,\n factory: ApiFactory<Api, Impl, Deps>,\n ) {\n const priority = ScopePriority[scope];\n const existing = this.factories.get(factory.api.id);\n if (existing && existing.priority >= priority) {\n return false;\n }\n\n this.factories.set(factory.api.id, { priority, factory });\n return true;\n }\n\n get<T>(\n api: ApiRef<T>,\n ): ApiFactory<T, T, { [x: string]: unknown }> | undefined {\n const tuple = this.factories.get(api.id);\n if (!tuple) {\n return undefined;\n }\n return tuple.factory as ApiFactory<T, T, { [x: string]: unknown }>;\n }\n\n getAllApis(): Set<AnyApiRef> {\n const refs = new Set<AnyApiRef>();\n for (const { factory } of this.factories.values()) {\n refs.add(factory.api);\n }\n return refs;\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 } from 'react';\nimport Button from '@material-ui/core/Button';\nimport { ErrorPanel, Progress, ErrorPage } from '@backstage/core-components';\nimport {\n MemoryRouter,\n useInRouterContext,\n BrowserRouter,\n} from 'react-router-dom';\nimport {\n AppComponents,\n BootErrorPageProps,\n ErrorBoundaryFallbackProps,\n} from '@backstage/core-plugin-api';\n\nexport function OptionallyWrapInRouter({ children }: { children: ReactNode }) {\n if (useInRouterContext()) {\n return <>{children}</>;\n }\n return <MemoryRouter>{children}</MemoryRouter>;\n}\n\nconst DefaultNotFoundPage = () => (\n <ErrorPage status=\"404\" statusMessage=\"PAGE NOT FOUND\" />\n);\n\nconst DefaultBootErrorPage = ({ step, error }: BootErrorPageProps) => {\n let message = '';\n if (step === 'load-config') {\n message = `The configuration failed to load, someone should have a look at this error: ${error.message}`;\n } else if (step === 'load-chunk') {\n message = `Lazy loaded chunk failed to load, try to reload the page: ${error.message}`;\n }\n // TODO: figure out a nicer way to handle routing on the error page, when it can be done.\n return (\n <OptionallyWrapInRouter>\n <ErrorPage statusMessage={message} stack={error.stack} />\n </OptionallyWrapInRouter>\n );\n};\n\nconst DefaultErrorBoundaryFallback = ({\n error,\n resetError,\n plugin,\n}: ErrorBoundaryFallbackProps) => {\n return (\n <ErrorPanel\n title={`Error in ${plugin?.getId()}`}\n defaultExpanded\n error={error}\n >\n <Button variant=\"outlined\" onClick={resetError}>\n Retry\n </Button>\n </ErrorPanel>\n );\n};\n\n/**\n * Creates a set of default components to pass along to {@link @backstage/core-app-api#createSpecializedApp}.\n *\n * @public\n */\nexport const components: AppComponents = {\n Progress,\n Router: BrowserRouter,\n NotFoundErrorPage: DefaultNotFoundPage,\n BootErrorPage: DefaultBootErrorPage,\n ErrorBoundaryFallback: DefaultErrorBoundaryFallback,\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 { DiscoveryApi } from '@backstage/core-plugin-api';\n\nconst ERROR_PREFIX = 'Invalid discovery URL pattern,';\n\n/**\n * UrlPatternDiscovery is a lightweight DiscoveryApi implementation.\n * It uses a single template string to construct URLs for each plugin.\n *\n * @public\n */\nexport class UrlPatternDiscovery implements DiscoveryApi {\n /**\n * Creates a new UrlPatternDiscovery given a template. The only\n * interpolation done for the template is to replace instances of `{{pluginId}}`\n * with the ID of the plugin being requested.\n *\n * Example pattern: `http://localhost:7007/api/{{ pluginId }}`\n */\n static compile(pattern: string): UrlPatternDiscovery {\n const parts = pattern.split(/\\{\\{\\s*pluginId\\s*\\}\\}/);\n const urlStr = parts.join('pluginId');\n\n let url;\n try {\n url = new URL(urlStr);\n } catch {\n throw new Error(`${ERROR_PREFIX} URL '${urlStr}' is invalid`);\n }\n if (url.hash) {\n throw new Error(`${ERROR_PREFIX} URL must not have a hash`);\n }\n if (url.search) {\n throw new Error(`${ERROR_PREFIX} URL must not have a query`);\n }\n if (urlStr.endsWith('/')) {\n throw new Error(`${ERROR_PREFIX} URL must not end with a slash`);\n }\n\n return new UrlPatternDiscovery(parts);\n }\n\n private constructor(private readonly parts: string[]) {}\n\n async getBaseUrl(pluginId: string): Promise<string> {\n return this.parts.join(encodeURIComponent(pluginId));\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 { Config } from '@backstage/config';\nimport { DiscoveryApi } from '@backstage/core-plugin-api';\nimport { UrlPatternDiscovery } from './UrlPatternDiscovery';\n\n/**\n * FrontendHostDiscovery is a config driven DiscoveryApi implementation.\n * It uses the app-config to determine the url for a plugin.\n *\n * @public\n */\nexport class FrontendHostDiscovery implements DiscoveryApi {\n /**\n * Creates a new FrontendHostDiscovery discovery instance by reading\n * the external target URL from the `discovery.endpoints` config section.\n *\n * eg.\n * ```yaml\n * discovery:\n * endpoints:\n * - target: https://internal.example.com/internal-catalog\n * plugins: [catalog]\n * - target: https://internal.example.com/secure/api/{{pluginId}}\n * plugins: [auth, permissions]\n * - target:\n * internal: https://internal.example.com/search\n * external: https://example.com/search\n * plugins: [search]\n * ```\n *\n * If a plugin is not declared in the config, the discovery will fall back to using the baseUrl with\n * the provided `pathPattern` appended. The default path pattern is `\"/api/{{ pluginId }}\"`.\n */\n static fromConfig(config: Config, options?: { pathPattern?: string }) {\n const path = options?.pathPattern ?? '/api/{{ pluginId }}';\n const baseUrl = config.getString('backend.baseUrl');\n\n const endpoints = config\n .getOptionalConfigArray('discovery.endpoints')\n ?.flatMap(e => {\n const target =\n typeof e.get('target') === 'object'\n ? e.getOptionalString('target.external')\n : e.getString('target');\n if (!target) {\n return [];\n }\n const discovery = UrlPatternDiscovery.compile(target);\n return e\n .getStringArray('plugins')\n .map(pluginId => [pluginId, discovery] as const);\n });\n\n return new FrontendHostDiscovery(\n new Map(endpoints),\n UrlPatternDiscovery.compile(`${baseUrl}${path}`),\n );\n }\n\n private constructor(\n private readonly endpoints: Map<string, DiscoveryApi>,\n private readonly defaultEndpoint: DiscoveryApi,\n ) {}\n\n async getBaseUrl(pluginId: string): Promise<string> {\n const endpoint = this.endpoints.get(pluginId);\n if (endpoint) {\n return endpoint.getBaseUrl(pluginId);\n }\n return this.defaultEndpoint.getBaseUrl(pluginId);\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 { Observable } from '@backstage/types';\nimport ObservableImpl from 'zen-observable';\n\n// TODO(Rugvip): These are stopgap and probably incomplete implementations of subjects.\n// If we add a more complete Observables library they should be replaced.\n\n/**\n * A basic implementation of ReactiveX publish subjects.\n *\n * A subject is a convenient way to create an observable when you want\n * to fan out a single value to all subscribers.\n *\n * See http://reactivex.io/documentation/subject.html\n */\nexport class PublishSubject<T>\n implements Observable<T>, ZenObservable.SubscriptionObserver<T>\n{\n private isClosed = false;\n private terminatingError?: Error;\n\n private readonly observable = new ObservableImpl<T>(subscriber => {\n if (this.isClosed) {\n if (this.terminatingError) {\n subscriber.error(this.terminatingError);\n } else {\n subscriber.complete();\n }\n return () => {};\n }\n\n this.subscribers.add(subscriber);\n return () => {\n this.subscribers.delete(subscriber);\n };\n });\n\n private readonly subscribers = new Set<\n ZenObservable.SubscriptionObserver<T>\n >();\n\n [Symbol.observable]() {\n return this;\n }\n\n get closed() {\n return this.isClosed;\n }\n\n next(value: T) {\n if (this.isClosed) {\n throw new Error('PublishSubject is closed');\n }\n this.subscribers.forEach(subscriber => subscriber.next(value));\n }\n\n error(error: Error) {\n if (this.isClosed) {\n throw new Error('PublishSubject is closed');\n }\n this.isClosed = true;\n this.terminatingError = error;\n this.subscribers.forEach(subscriber => subscriber.error(error));\n }\n\n complete() {\n if (this.isClosed) {\n throw new Error('PublishSubject is closed');\n }\n this.isClosed = true;\n this.subscribers.forEach(subscriber => subscriber.complete());\n }\n\n subscribe(observer: ZenObservable.Observer<T>): ZenObservable.Subscription;\n subscribe(\n onNext: (value: T) => void,\n onError?: (error: any) => void,\n onComplete?: () => void,\n ): ZenObservable.Subscription;\n subscribe(\n onNext: ZenObservable.Observer<T> | ((value: T) => void),\n onError?: (error: any) => void,\n onComplete?: () => void,\n ): ZenObservable.Subscription {\n const observer =\n typeof onNext === 'function'\n ? {\n next: onNext,\n error: onError,\n complete: onComplete,\n }\n : onNext;\n\n return this.observable.subscribe(observer);\n }\n}\n\n/**\n * A basic implementation of ReactiveX behavior subjects.\n *\n * A subject is a convenient way to create an observable when you want\n * to fan out a single value to all subscribers.\n *\n * The BehaviorSubject will emit the most recently emitted value or error\n * whenever a new observer subscribes to the subject.\n *\n * See http://reactivex.io/documentation/subject.html\n */\n\nexport class BehaviorSubject<T>\n implements Observable<T>, ZenObservable.SubscriptionObserver<T>\n{\n private isClosed: boolean;\n private currentValue: T;\n private terminatingError: Error | undefined;\n private readonly observable: Observable<T>;\n\n constructor(value: T) {\n this.isClosed = false;\n this.currentValue = value;\n this.terminatingError = undefined;\n this.observable = new ObservableImpl<T>(subscriber => {\n if (this.isClosed) {\n if (this.terminatingError) {\n subscriber.error(this.terminatingError);\n } else {\n subscriber.complete();\n }\n return () => {};\n }\n\n subscriber.next(this.currentValue);\n\n this.subscribers.add(subscriber);\n return () => {\n this.subscribers.delete(subscriber);\n };\n });\n }\n\n private readonly subscribers = new Set<\n ZenObservable.SubscriptionObserver<T>\n >();\n\n [Symbol.observable]() {\n return this;\n }\n\n get closed() {\n return this.isClosed;\n }\n\n next(value: T) {\n if (this.isClosed) {\n throw new Error('BehaviorSubject is closed');\n }\n this.currentValue = value;\n this.subscribers.forEach(subscriber => subscriber.next(value));\n }\n\n error(error: Error) {\n if (this.isClosed) {\n throw new Error('BehaviorSubject is closed');\n }\n this.isClosed = true;\n this.terminatingError = error;\n this.subscribers.forEach(subscriber => subscriber.error(error));\n }\n\n complete() {\n if (this.isClosed) {\n throw new Error('BehaviorSubject is closed');\n }\n this.isClosed = true;\n this.subscribers.forEach(subscriber => subscriber.complete());\n }\n\n subscribe(observer: ZenObservable.Observer<T>): ZenObservable.Subscription;\n subscribe(\n onNext: (value: T) => void,\n onError?: (error: any) => void,\n onComplete?: () => void,\n ): ZenObservable.Subscription;\n subscribe(\n onNext: ZenObservable.Observer<T> | ((value: T) => void),\n onError?: (error: any) => void,\n onComplete?: () => void,\n ): ZenObservable.Subscription {\n const observer =\n typeof onNext === 'function'\n ? {\n next: onNext,\n error: onError,\n complete: onComplete,\n }\n : onNext;\n\n return this.observable.subscribe(observer);\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 { AlertApi, AlertMessage } from '@backstage/core-plugin-api';\nimport { Observable } from '@backstage/types';\nimport { PublishSubject } from '../../../lib/subjects';\n\n/**\n * Base implementation for the AlertApi that simply forwards alerts to consumers.\n *\n * @public\n */\nexport class AlertApiForwarder implements AlertApi {\n private readonly subject = new PublishSubject<AlertMessage>();\n\n post(alert: AlertMessage) {\n this.subject.next(alert);\n }\n\n alert$(): Observable<AlertMessage> {\n return this.subject;\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 */\nimport { AnalyticsApi, AnalyticsEvent } from '@backstage/core-plugin-api';\n\n/**\n * Base implementation for the AnalyticsApi that does nothing.\n *\n * @public\n */\nexport class NoOpAnalyticsApi implements AnalyticsApi {\n captureEvent(_event: AnalyticsEvent): void {}\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 */\nimport {\n ErrorApi,\n ErrorApiError,\n ErrorApiErrorContext,\n AlertApi,\n} from '@backstage/core-plugin-api';\n\n/**\n * Decorates an ErrorApi by also forwarding error messages\n * to the alertApi with an 'error' severity.\n *\n * @public\n */\nexport class ErrorAlerter implements ErrorApi {\n constructor(\n private readonly alertApi: AlertApi,\n private readonly errorApi: ErrorApi,\n ) {}\n\n post(error: ErrorApiError, context?: ErrorApiErrorContext) {\n if (!context?.hidden) {\n this.alertApi.post({ message: error.message, severity: 'error' });\n }\n\n return this.errorApi.post(error, context);\n }\n\n error$() {\n return this.errorApi.error$();\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 ErrorApi,\n ErrorApiError,\n ErrorApiErrorContext,\n} from '@backstage/core-plugin-api';\nimport { Observable } from '@backstage/types';\nimport { PublishSubject } from '../../../lib/subjects';\n\n/**\n * Base implementation for the ErrorApi that simply forwards errors to consumers.\n *\n * @public\n */\nexport class ErrorApiForwarder implements ErrorApi {\n private readonly subject = new PublishSubject<{\n error: Error;\n context?: ErrorApiErrorContext;\n }>();\n\n post(error: ErrorApiError, context?: ErrorApiErrorContext) {\n this.subject.next({ error, context });\n }\n\n error$(): Observable<{ error: Error; context?: ErrorApiErrorContext }> {\n return this.subject;\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 ErrorApi,\n ErrorApiError,\n ErrorApiErrorContext,\n} from '@backstage/core-plugin-api';\n\n/**\n * Utility class that helps with error forwarding.\n *\n * @public\n */\nexport class UnhandledErrorForwarder {\n /**\n * Add event listener, such that unhandled errors can be forwarded using an given `ErrorApi` instance\n */\n static forward(errorApi: ErrorApi, errorContext: ErrorApiErrorContext) {\n window.addEventListener(\n 'unhandledrejection',\n (e: PromiseRejectionEvent) => {\n errorApi.post(e.reason as ErrorApiError, errorContext);\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 {\n StorageApi,\n StorageValueSnapshot,\n ErrorApi,\n} from '@backstage/core-plugin-api';\nimport { JsonValue, Observable } from '@backstage/types';\nimport ObservableImpl from 'zen-observable';\n\nexport const buckets = new Map<string, WebStorage>();\n\n/**\n * An implementation of the storage API, that uses the browser's local storage.\n *\n * @public\n */\nexport class WebStorage implements StorageApi {\n constructor(\n private readonly namespace: string,\n private readonly errorApi: ErrorApi,\n ) {}\n\n private static hasSubscribed = false;\n\n static create(options: {\n errorApi: ErrorApi;\n namespace?: string;\n }): WebStorage {\n return new WebStorage(options.namespace ?? '', options.errorApi);\n }\n\n private static addStorageEventListener() {\n window.addEventListener('storage', event => {\n for (const [bucketPath, webStorage] of buckets.entries()) {\n if (event.key?.startsWith(bucketPath)) {\n webStorage.handleStorageChange(event.key);\n }\n }\n });\n }\n\n get<T>(key: string): T | undefined {\n return this.snapshot(key).value as T | undefined;\n }\n\n snapshot<T extends JsonValue>(key: string): StorageValueSnapshot<T> {\n let value = undefined;\n let presence: 'present' | 'absent' = 'absent';\n try {\n const item = localStorage.getItem(this.getKeyName(key));\n if (item) {\n value = JSON.parse(item, (_key, val) => {\n if (typeof val === 'object' && val !== null) {\n Object.freeze(val);\n }\n return val;\n });\n presence = 'present';\n }\n } catch (e) {\n this.errorApi.post(\n new Error(`Error when parsing JSON config from storage for: ${key}`),\n );\n }\n return { key, value, presence };\n }\n\n forBucket(name: string): WebStorage {\n const bucketPath = `${this.namespace}/${name}`;\n if (!buckets.has(bucketPath)) {\n buckets.set(bucketPath, new WebStorage(bucketPath, this.errorApi));\n }\n return buckets.get(bucketPath)!;\n }\n\n async set<T>(key: string, data: T): Promise<void> {\n localStorage.setItem(this.getKeyName(key), JSON.stringify(data));\n this.notifyChanges(key);\n }\n\n async remove(key: string): Promise<void> {\n localStorage.removeItem(this.getKeyName(key));\n this.notifyChanges(key);\n }\n\n observe$<T extends JsonValue>(\n key: string,\n ): Observable<StorageValueSnapshot<T>> {\n if (!WebStorage.hasSubscribed) {\n WebStorage.addStorageEventListener();\n WebStorage.hasSubscribed = true;\n }\n return this.observable.filter(({ key: messageKey }) => messageKey === key);\n }\n\n private handleStorageChange(eventKey: StorageEvent['key']) {\n if (!eventKey?.startsWith(this.namespace)) {\n return;\n }\n // Grab the part of this key that is local to this bucket\n const trimmedKey = eventKey?.slice(`${this.namespace}/`.length);\n\n // If the key still contains a slash, it means it's a sub-bucket\n if (!trimmedKey.includes('/')) {\n this.notifyChanges(decodeURIComponent(trimmedKey));\n }\n }\n\n private getKeyName(key: string) {\n return `${this.namespace}/${encodeURIComponent(key)}`;\n }\n\n private notifyChanges(key: string) {\n const snapshot = this.snapshot(key);\n for (const subscription of this.subscribers) {\n subscription.next(snapshot);\n }\n }\n\n private subscribers = new Set<\n ZenObservable.SubscriptionObserver<StorageValueSnapshot<JsonValue>>\n >();\n\n private readonly observable = new ObservableImpl<\n StorageValueSnapshot<JsonValue>\n >(subscriber => {\n this.subscribers.add(subscriber);\n return () => {\n this.subscribers.delete(subscriber);\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 { Config } from '@backstage/config';\nimport { IdentityApi } from '@backstage/core-plugin-api';\nimport { FetchMiddleware } from './types';\n\n/**\n * A fetch middleware, which injects a Backstage token header when the user is\n * signed in.\n */\nexport class IdentityAuthInjectorFetchMiddleware implements FetchMiddleware {\n static create(options: {\n identityApi: IdentityApi;\n config?: Config;\n urlPrefixAllowlist?: string[];\n allowUrl?: (url: string) => boolean;\n header?: {\n name: string;\n value: (backstageToken: string) => string;\n };\n }): IdentityAuthInjectorFetchMiddleware {\n const matcher = buildMatcher(options);\n const headerName = options.header?.name || 'authorization';\n const headerValue = options.header?.value || (token => `Bearer ${token}`);\n\n return new IdentityAuthInjectorFetchMiddleware(\n options.identityApi,\n matcher,\n headerName,\n headerValue,\n );\n }\n\n /**\n * Returns an array of plugin URL prefixes derived from the static `discovery`\n * configuration, to be used as `urlPrefixAllowlist` option of {@link create}.\n */\n static getDiscoveryUrlPrefixes(config: Config): string[] {\n const endpointConfigs =\n config.getOptionalConfigArray('discovery.endpoints') || [];\n return endpointConfigs.flatMap(c => {\n const target =\n typeof c.get('target') === 'object'\n ? c.getString('target.external')\n : c.getString('target');\n const plugins = c.getStringArray('plugins');\n return plugins.map(pluginId =>\n target.replace(/\\{\\{\\s*pluginId\\s*\\}\\}/g, pluginId),\n );\n });\n }\n\n constructor(\n public readonly identityApi: IdentityApi,\n public readonly allowUrl: (url: string) => boolean,\n public readonly headerName: string,\n public readonly headerValue: (pluginId: string) => string,\n ) {}\n\n apply(next: typeof fetch): typeof fetch {\n return async (input, init) => {\n // Skip this middleware if the header already exists, or if the URL\n // doesn't match any of the allowlist items, or if there was no token.\n // NOTE(freben): The \"as any\" casts here and below are because of subtle\n // undici type differences that happened in a node types bump. Those are\n // immaterial to the code at hand at runtime, as the global fetch and\n // Request are always taken from the same place.\n const request = new Request(input as any, init);\n const { token } = await this.identityApi.getCredentials();\n if (\n request.headers.get(this.headerName) ||\n typeof token !== 'string' ||\n !token ||\n !this.allowUrl(request.url)\n ) {\n return next(input as any, init);\n }\n\n request.headers.set(this.headerName, this.headerValue(token));\n return next(request);\n };\n }\n}\n\nfunction buildMatcher(options: {\n config?: Config;\n urlPrefixAllowlist?: string[];\n allowUrl?: (url: string) => boolean;\n}): (url: string) => boolean {\n if (options.allowUrl) {\n return options.allowUrl;\n } else if (options.urlPrefixAllowlist) {\n return buildPrefixMatcher(options.urlPrefixAllowlist);\n } else if (options.config) {\n return buildPrefixMatcher([\n options.config.getString('backend.baseUrl'),\n ...IdentityAuthInjectorFetchMiddleware.getDiscoveryUrlPrefixes(\n options.config,\n ),\n ]);\n }\n return () => false;\n}\n\nfunction buildPrefixMatcher(prefixes: string[]): (url: string) => boolean {\n const trimmedPrefixes = prefixes.map(prefix => prefix.replace(/\\/$/, ''));\n return url =>\n trimmedPrefixes.some(\n prefix => url === prefix || url.startsWith(`${prefix}/`),\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 { DiscoveryApi } from '@backstage/core-plugin-api';\nimport { FetchMiddleware } from './types';\n\nfunction join(left: string, right: string): string {\n if (!right || right === '/') {\n return left;\n }\n\n return `${left.replace(/\\/$/, '')}/${right.replace(/^\\//, '')}`;\n}\n\n/**\n * Handles translation from plugin://some-plugin-id/<path> to concrete http(s)\n * URLs.\n */\nexport class PluginProtocolResolverFetchMiddleware implements FetchMiddleware {\n constructor(private readonly discoveryApi: DiscoveryApi) {}\n\n apply(next: typeof fetch): typeof fetch {\n return async (input, init) => {\n // NOTE(freben): The \"as any\" casts here and below are because of subtle\n // undici type differences that happened in a node types bump. Those are\n // immaterial to the code at hand at runtime, as the global fetch and\n // Request are always taken from the same place.\n const request = new Request(input as any, init);\n const prefix = 'plugin://';\n\n if (!request.url.startsWith(prefix)) {\n return next(input as any, init);\n }\n\n // Switch to a known protocol, since browser URL parsing misbehaves wildly\n // on foreign protocols\n const { hostname, pathname, search, hash, username, password } = new URL(\n `http://${request.url.substring(prefix.length)}`,\n );\n\n let base = await this.discoveryApi.getBaseUrl(hostname);\n if (username || password) {\n const baseUrl = new URL(base);\n const authority = `${username}${password ? `:${password}` : ''}@`;\n base = `${baseUrl.protocol}//${authority}${baseUrl.host}${baseUrl.pathname}`;\n }\n\n const target = `${join(base, pathname)}${search}${hash}`;\n return next(\n target,\n typeof input === 'string' || isUrl(input) ? init : (input as any),\n );\n };\n }\n}\n\nfunction isUrl(a: unknown): a is URL {\n return typeof a === 'object' && a?.constructor === URL;\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';\nimport { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api';\nimport { IdentityAuthInjectorFetchMiddleware } from './IdentityAuthInjectorFetchMiddleware';\nimport { PluginProtocolResolverFetchMiddleware } from './PluginProtocolResolverFetchMiddleware';\nimport { FetchMiddleware } from './types';\n\n/**\n * A collection of common middlewares for the FetchApi.\n *\n * @public\n */\nexport class FetchMiddlewares {\n /**\n * Handles translation from `plugin://` URLs to concrete http(s) URLs based on\n * the discovery API.\n *\n * @remarks\n *\n * If the request is for `plugin://catalog/entities?filter=x=y`, the discovery\n * API will be queried for `'catalog'`. If it returned\n * `https://backstage.example.net/api/catalog`, the resulting query would be\n * `https://backstage.example.net/api/catalog/entities?filter=x=y`.\n *\n * If the incoming URL protocol was not `plugin`, the request is just passed\n * through verbatim to the underlying implementation.\n */\n static resolvePluginProtocol(options: {\n discoveryApi: DiscoveryApi;\n }): FetchMiddleware {\n return new PluginProtocolResolverFetchMiddleware(options.discoveryApi);\n }\n\n /**\n * Injects a Backstage token header when the user is signed in.\n *\n * @remarks\n *\n * Per default, an `Authorization: Bearer <token>` is generated. This can be\n * customized using the `header` option.\n *\n * The header injection only happens on allowlisted URLs. Per default, if the\n * `config` option is passed in, the `backend.baseUrl` is allowlisted, unless\n * the `urlPrefixAllowlist` or `allowUrl` options are passed in, in which case\n * they take precedence. If you pass in neither config nor an\n * allowlist/callback, the middleware will have no effect since effectively no\n * request will match the (nonexistent) rules.\n */\n static injectIdentityAuth(options: {\n identityApi: IdentityApi;\n config?: Config;\n urlPrefixAllowlist?: string[];\n allowUrl?: (url: string) => boolean;\n header?: {\n name: string;\n value: (backstageToken: string) => string;\n };\n }): FetchMiddleware {\n return IdentityAuthInjectorFetchMiddleware.create(options);\n }\n\n private constructor() {}\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 { Observable } from '@backstage/types';\nimport { BehaviorSubject } from '../../../lib/subjects';\n\ntype RequestQueueEntry<ResultType> = {\n scopes: Set<string>;\n resolve: (value: ResultType | PromiseLike<ResultType>) => void;\n reject: (reason: Error) => void;\n};\n\nexport type PendingRequest<ResultType> = {\n scopes: Set<string> | undefined;\n resolve: (value: ResultType) => void;\n reject: (reason: Error) => void;\n};\n\nexport function hasScopes(\n searched: Set<string>,\n searchFor: Set<string>,\n): boolean {\n for (const scope of searchFor) {\n if (!searched.has(scope)) {\n return false;\n }\n }\n return true;\n}\n\nexport function joinScopes(\n scopes: Set<string>,\n ...moreScopess: Set<string>[]\n): Set<string> {\n const result = new Set(scopes);\n\n for (const moreScopes of moreScopess) {\n for (const scope of moreScopes) {\n result.add(scope);\n }\n }\n\n return result;\n}\n\n/**\n * The OAuthPendingRequests class is a utility for managing and observing\n * a stream of requests for oauth scopes for a single provider, and resolving\n * them correctly once requests are fulfilled.\n */\nexport class OAuthPendingRequests<ResultType> {\n private requests: RequestQueueEntry<ResultType>[] = [];\n private subject = new BehaviorSubject<PendingRequest<ResultType>>(\n this.getCurrentPending(),\n );\n\n request(scopes: Set<string>): Promise<ResultType> {\n return new Promise((resolve, reject) => {\n this.requests.push({ scopes, resolve, reject });\n\n this.subject.next(this.getCurrentPending());\n });\n }\n\n resolve(scopes: Set<string>, result: ResultType): void {\n this.requests = this.requests.filter(request => {\n if (hasScopes(scopes, request.scopes)) {\n request.resolve(result);\n return false;\n }\n return true;\n });\n\n this.subject.next(this.getCurrentPending());\n }\n\n reject(error: Error) {\n this.requests.forEach(request => request.reject(error));\n this.requests = [];\n\n this.subject.next(this.getCurrentPending());\n }\n\n pending(): Observable<PendingRequest<ResultType>> {\n return this.subject;\n }\n\n private getCurrentPending(): PendingRequest<ResultType> {\n const currentScopes =\n this.requests.length === 0\n ? undefined\n : this.requests\n .slice(1)\n .reduce(\n (acc, current) => joinScopes(acc, current.scopes),\n this.requests[0].scopes,\n );\n\n return {\n scopes: currentScopes,\n resolve: (value: ResultType) => {\n if (currentScopes) {\n this.resolve(currentScopes, value);\n }\n },\n reject: (reason: Error) => {\n if (currentScopes) {\n this.reject(reason);\n }\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 {\n OAuthRequestApi,\n PendingOAuthRequest,\n OAuthRequester,\n OAuthRequesterOptions,\n} from '@backstage/core-plugin-api';\nimport { Observable } from '@backstage/types';\nimport { OAuthPendingRequests, PendingRequest } from './OAuthPendingRequests';\nimport { PublishSubject } from '../../../lib/subjects';\n\n/**\n * The OAuthRequestManager is an implementation of the OAuthRequestApi.\n *\n * The purpose of this class and the API is to read a stream of incoming requests\n * of OAuth access tokens from different providers with varying scope, and funnel\n * them all together into a single request for each OAuth provider.\n *\n * @public\n */\nexport class OAuthRequestManager implements OAuthRequestApi {\n private readonly subject = new PublishSubject<PendingOAuthRequest[]>();\n private currentRequests: PendingOAuthRequest[] = [];\n private handlerCount = 0;\n\n createAuthRequester<T>(options: OAuthRequesterOptions<T>): OAuthRequester<T> {\n const handler = new OAuthPendingRequests<T>();\n\n const index = this.handlerCount;\n this.handlerCount++;\n\n handler.pending().subscribe({\n next: scopeRequest => {\n const newRequests = this.currentRequests.slice();\n const request = this.makeAuthRequest(scopeRequest, options);\n if (!request) {\n delete newRequests[index];\n } else {\n newRequests[index] = request;\n }\n this.currentRequests = newRequests;\n // Convert from sparse array to array of present items only\n this.subject.next(newRequests.filter(Boolean));\n },\n });\n\n return scopes => {\n return handler.request(scopes);\n };\n }\n\n // Converts the pending request and popup options into a popup request that we can forward to subscribers.\n private makeAuthRequest(\n request: PendingRequest<any>,\n options: OAuthRequesterOptions<any>,\n ): PendingOAuthRequest | undefined {\n const { scopes } = request;\n if (!scopes) {\n return undefined;\n }\n\n return {\n provider: options.provider,\n trigger: async () => {\n const result = await options.onAuthRequest(scopes);\n request.resolve(result);\n },\n reject: () => {\n const error = new Error('Login failed, rejected by user');\n error.name = 'RejectedError';\n request.reject(error);\n },\n };\n }\n\n authRequest$(): Observable<PendingOAuthRequest[]> {\n return this.subject;\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 */\nimport {\n AuthProviderInfo,\n ConfigApi,\n DiscoveryApi,\n OAuthRequestApi,\n OAuthRequester,\n} from '@backstage/core-plugin-api';\nimport { openLoginPopup } from '../loginPopup';\nimport {\n AuthConnector,\n AuthConnectorCreateSessionOptions,\n PopupOptions,\n AuthConnectorRefreshSessionOptions,\n} from './types';\n\nlet warned = false;\n\ntype Options<AuthSession> = {\n /**\n * DiscoveryApi instance used to locate the auth backend endpoint.\n */\n discoveryApi: DiscoveryApi;\n /**\n * Environment hint passed on to auth backend, for example 'production' or 'development'\n */\n environment: string;\n /**\n * Information about the auth provider to be shown to the user.\n * The ID Must match the backend auth plugin configuration, for example 'google'.\n */\n provider: AuthProviderInfo;\n /**\n * API used to instantiate an auth requester.\n */\n oauthRequestApi: OAuthRequestApi;\n /**\n * Function used to join together a set of scopes, defaults to joining with a space character.\n */\n joinScopes?: (scopes: Set<string>) => string;\n /**\n * Function used to transform an auth response into the session type.\n */\n sessionTransform?(response: any): AuthSession | Promise<AuthSession>;\n /**\n * ConfigApi instance used to configure authentication flow of pop-up or redirect.\n */\n configApi?: ConfigApi;\n /**\n * Options used to configure auth popup\n */\n popupOptions?: PopupOptions;\n};\n\nfunction defaultJoinScopes(scopes: Set<string>) {\n return [...scopes].join(' ');\n}\n\n/**\n * DefaultAuthConnector is the default auth connector in Backstage. It talks to the\n * backend auth plugin through the standardized API, and requests user permission\n * via the OAuthRequestApi.\n */\nexport class DefaultAuthConnector<AuthSession>\n implements AuthConnector<AuthSession>\n{\n private readonly discoveryApi: DiscoveryApi;\n private readonly environment: string;\n private readonly provider: AuthProviderInfo;\n private readonly joinScopesFunc: (scopes: Set<string>) => string;\n private readonly authRequester: OAuthRequester<AuthSession>;\n private readonly sessionTransform: (response: any) => Promise<AuthSession>;\n private readonly enableExperimentalRedirectFlow: boolean;\n private readonly popupOptions: PopupOptions | undefined;\n constructor(options: Options<AuthSession>) {\n const {\n configApi,\n discoveryApi,\n environment,\n provider,\n joinScopes = defaultJoinScopes,\n oauthRequestApi,\n sessionTransform = id => id,\n popupOptions,\n } = options;\n\n if (!warned && !configApi) {\n // eslint-disable-next-line no-console\n console.warn(\n 'DEPRECATION WARNING: Authentication providers require a configApi instance to configure the authentication flow. Please provide one to the authentication provider constructor.',\n );\n warned = true;\n }\n\n this.enableExperimentalRedirectFlow = configApi\n ? configApi.getOptionalBoolean('enableExperimentalRedirectFlow') ?? false\n : false;\n\n this.authRequester = oauthRequestApi.createAuthRequester({\n provider,\n onAuthRequest: async scopes => {\n if (!this.enableExperimentalRedirectFlow) {\n return this.showPopup(scopes);\n }\n return this.executeRedirect(scopes);\n },\n });\n\n this.discoveryApi = discoveryApi;\n this.environment = environment;\n this.provider = provider;\n this.joinScopesFunc = joinScopes;\n this.sessionTransform = sessionTransform;\n this.popupOptions = popupOptions;\n }\n\n async createSession(\n options: AuthConnectorCreateSessionOptions,\n ): Promise<AuthSession> {\n if (options.instantPopup) {\n if (this.enableExperimentalRedirectFlow) {\n return this.executeRedirect(options.scopes);\n }\n return this.showPopup(options.scopes);\n }\n return this.authRequester(options.scopes);\n }\n\n async refreshSession(\n options?: AuthConnectorRefreshSessionOptions,\n ): Promise<any> {\n const res = await fetch(\n await this.buildUrl('/refresh', {\n optional: true,\n ...(options && { scope: this.joinScopesFunc(options.scopes) }),\n }),\n {\n headers: {\n 'x-requested-with': 'XMLHttpRequest',\n },\n credentials: 'include',\n },\n ).catch(error => {\n throw new Error(`Auth refresh request failed, ${error}`);\n });\n\n if (!res.ok) {\n const error: any = new Error(\n `Auth refresh request failed, ${res.statusText}`,\n );\n error.status = res.status;\n throw error;\n }\n\n const authInfo = await res.json();\n\n if (authInfo.error) {\n const error = new Error(authInfo.error.message);\n if (authInfo.error.name) {\n error.name = authInfo.error.name;\n }\n throw error;\n }\n return await this.sessionTransform(authInfo);\n }\n\n async removeSession(): Promise<void> {\n const res = await fetch(await this.buildUrl('/logout'), {\n method: 'POST',\n headers: {\n 'x-requested-with': 'XMLHttpRequest',\n },\n credentials: 'include',\n }).catch(error => {\n throw new Error(`Logout request failed, ${error}`);\n });\n\n if (!res.ok) {\n const error: any = new Error(`Logout request failed, ${res.statusText}`);\n error.status = res.status;\n throw error;\n }\n }\n\n private async showPopup(scopes: Set<string>): Promise<AuthSession> {\n const scope = this.joinScopesFunc(scopes);\n const popupUrl = await this.buildUrl('/start', {\n scope,\n origin: window.location.origin,\n flow: 'popup',\n });\n\n const width = this.popupOptions?.size?.fullscreen\n ? window.screen.width\n : this.popupOptions?.size?.width || 450;\n\n const height = this.popupOptions?.size?.fullscreen\n ? window.screen.height\n : this.popupOptions?.size?.height || 730;\n\n const payload = await openLoginPopup({\n url: popupUrl,\n name: `${this.provider.title} Login`,\n width,\n height,\n });\n\n return await this.sessionTransform(payload);\n }\n\n private async executeRedirect(scopes: Set<string>): Promise<AuthSession> {\n const scope = this.joinScopesFunc(scopes);\n // redirect to auth api\n window.location.href = await this.buildUrl('/start', {\n scope,\n origin: window.location.origin,\n redirectUrl: window.location.href,\n flow: 'redirect',\n });\n // return a promise that never resolves\n return new Promise(() => {});\n }\n\n private async buildUrl(\n path: string,\n query?: { [key: string]: string | boolean | undefined },\n ): Promise<string> {\n const baseUrl = await this.discoveryApi.getBaseUrl('auth');\n const queryString = this.buildQueryString({\n ...query,\n env: this.environment,\n });\n\n return `${baseUrl}/${this.provider.id}${path}${queryString}`;\n }\n\n private buildQueryString(query?: {\n [key: string]: string | boolean | undefined;\n }): string {\n if (!query) {\n return '';\n }\n\n const queryString = Object.entries<string | boolean | undefined>(query)\n .map(([key, value]) => {\n if (typeof value === 'string') {\n return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;\n } else if (value) {\n return encodeURIComponent(key);\n }\n return undefined;\n })\n .filter(Boolean)\n .join('&');\n\n if (!queryString) {\n return '';\n }\n return `?${queryString}`;\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\n/**\n * Options used to open a login popup.\n *\n * @public\n */\nexport type OpenLoginPopupOptions = {\n /**\n * The URL that the auth popup should point to\n */\n url: string;\n\n /**\n * The name of the popup, as in second argument to window.open\n */\n name: string;\n\n /**\n * The width of the popup in pixels, defaults to 500\n */\n width?: number;\n\n /**\n * The height of the popup in pixels, defaults to 700\n */\n height?: number;\n};\n\ntype AuthResult =\n | {\n type: 'authorization_response';\n response: unknown;\n }\n | {\n type: 'authorization_response';\n error: {\n name: string;\n message: string;\n };\n };\n\n/**\n * Show a popup pointing to a URL that starts an auth flow. Implementing the receiving\n * end of the postMessage mechanism outlined in https://tools.ietf.org/html/draft-sakimura-oauth-wmrm-00\n *\n * The redirect handler of the flow should use postMessage to communicate back\n * to the app window. The message posted to the app must match the AuthResult type.\n *\n * The returned promise resolves to the response of the message that was posted from the auth popup.\n *\n * @public\n */\nexport function openLoginPopup(\n options: OpenLoginPopupOptions,\n): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const width = options.width || 500;\n const height = options.height || 700;\n const left = window.screen.width / 2 - width / 2;\n const top = window.screen.height / 2 - height / 2;\n\n const origin = new URL(options.url).origin;\n\n const popup = window.open(\n options.url,\n options.name,\n `menubar=no,location=no,resizable=no,scrollbars=no,status=no,width=${width},height=${height},top=${top},left=${left}`,\n );\n\n let targetOrigin = '';\n\n if (!popup || typeof popup.closed === 'undefined' || popup.closed) {\n const error = new Error('Failed to open auth popup.');\n error.name = 'PopupRejectedError';\n reject(error);\n return;\n }\n\n const messageListener = (event: MessageEvent) => {\n if (event.source !== popup) {\n return;\n }\n if (event.origin !== origin) {\n return;\n }\n const { data } = event;\n\n if (data.type === 'config_info') {\n targetOrigin = data.targetOrigin;\n return;\n }\n\n if (data.type !== 'authorization_response') {\n return;\n }\n const authResult = data as AuthResult;\n\n if ('error' in authResult) {\n const error = new Error(authResult.error.message);\n error.name = authResult.error.name;\n // TODO: proper error type\n // error.extra = authResult.error.extra;\n reject(error);\n } else {\n resolve(authResult.response);\n }\n done();\n };\n\n const intervalId = setInterval(() => {\n if (popup.closed) {\n const errMessage = `Login failed, ${\n targetOrigin && targetOrigin !== window.location.origin\n ? `Incorrect app origin, expected ${targetOrigin}`\n : 'popup was closed'\n }`;\n const error = new Error(errMessage);\n error.name = 'PopupClosedError';\n reject(error);\n done();\n }\n }, 100);\n\n function done() {\n window.removeEventListener('message', messageListener);\n clearInterval(intervalId);\n }\n\n window.addEventListener('message', messageListener);\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 { SessionScopesFunc } from './types';\n\nexport function hasScopes(\n searched: Set<string>,\n searchFor: Set<string>,\n): boolean {\n for (const scope of searchFor) {\n if (!searched.has(scope)) {\n return false;\n }\n }\n return true;\n}\n\ntype ScopeHelperOptions<T> = {\n sessionScopes: SessionScopesFunc<T> | undefined;\n defaultScopes?: Set<string>;\n};\n\nexport class SessionScopeHelper<T> {\n constructor(private readonly options: ScopeHelperOptions<T>) {}\n\n sessionExistsAndHasScope(\n session: T | undefined,\n scopes?: Set<string>,\n ): boolean {\n if (!session) {\n return false;\n }\n if (!scopes) {\n return true;\n }\n if (this.options.sessionScopes === undefined) {\n return true;\n }\n const sessionScopes = this.options.sessionScopes(session);\n return hasScopes(sessionScopes, scopes);\n }\n\n getExtendedScope(session: T | undefined, scopes?: Set<string>) {\n const newScope = new Set(this.options.defaultScopes);\n if (session && this.options.sessionScopes !== undefined) {\n const sessionScopes = this.options.sessionScopes(session);\n for (const scope of sessionScopes) {\n newScope.add(scope);\n }\n }\n if (scopes) {\n for (const scope of scopes) {\n newScope.add(scope);\n }\n }\n return newScope;\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 { BehaviorSubject } from '../subjects';\nimport { SessionState } from '@backstage/core-plugin-api';\nimport { Observable } from '@backstage/types';\n\nexport class SessionStateTracker {\n private readonly subject = new BehaviorSubject<SessionState>(\n SessionState.SignedOut,\n );\n\n private signedIn: boolean = false;\n\n setIsSignedIn(isSignedIn: boolean) {\n if (this.signedIn !== isSignedIn) {\n this.signedIn = isSignedIn;\n this.subject.next(\n this.signedIn ? SessionState.SignedIn : SessionState.SignedOut,\n );\n }\n }\n\n sessionState$(): Observable<SessionState> {\n return this.subject;\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 SessionManager,\n SessionScopesFunc,\n SessionShouldRefreshFunc,\n GetSessionOptions,\n} from './types';\nimport { AuthConnector } from '../AuthConnector';\nimport { SessionScopeHelper, hasScopes } from './common';\nimport { SessionStateTracker } from './SessionStateTracker';\n\ntype Options<T> = {\n /** The connector used for acting on the auth session */\n connector: AuthConnector<T>;\n /** Used to get the scope of the session */\n sessionScopes: SessionScopesFunc<T>;\n /** Used to check if the session needs to be refreshed */\n sessionShouldRefresh: SessionShouldRefreshFunc<T>;\n /** The default scopes that should always be present in a session, defaults to none. */\n defaultScopes?: Set<string>;\n};\n\n/**\n * RefreshingAuthSessionManager manages an underlying session that has\n * and expiration time and needs to be refreshed periodically.\n */\nexport class RefreshingAuthSessionManager<T> implements SessionManager<T> {\n private readonly connector: AuthConnector<T>;\n private readonly helper: SessionScopeHelper<T>;\n private readonly sessionScopesFunc: SessionScopesFunc<T>;\n private readonly sessionShouldRefreshFunc: SessionShouldRefreshFunc<T>;\n private readonly stateTracker = new SessionStateTracker();\n\n private refreshPromise?: Promise<T>;\n private currentSession: T | undefined;\n\n constructor(options: Options<T>) {\n const {\n connector,\n defaultScopes = new Set(),\n sessionScopes,\n sessionShouldRefresh,\n } = options;\n\n this.connector = connector;\n this.sessionScopesFunc = sessionScopes;\n this.sessionShouldRefreshFunc = sessionShouldRefresh;\n this.helper = new SessionScopeHelper({ sessionScopes, defaultScopes });\n }\n\n async getSession(options: GetSessionOptions): Promise<T | undefined> {\n let alreadyTriedToRefreshSession = false;\n if (\n this.helper.sessionExistsAndHasScope(this.currentSession, options.scopes)\n ) {\n const shouldRefresh = this.sessionShouldRefreshFunc(this.currentSession!);\n if (!shouldRefresh) {\n return this.currentSession!;\n }\n\n alreadyTriedToRefreshSession = true;\n\n try {\n const refreshedSession = await this.collapsedSessionRefresh(\n options.scopes,\n );\n const currentScopes = this.sessionScopesFunc(this.currentSession!);\n const refreshedScopes = this.sessionScopesFunc(refreshedSession);\n if (hasScopes(refreshedScopes, currentScopes)) {\n this.currentSession = refreshedSession;\n }\n return refreshedSession;\n } catch (error) {\n this.removeLocalSession();\n\n if (options.optional) {\n return undefined;\n }\n // If the refresh attempt fails we assume we don't have a session, so continue to create one\n }\n }\n\n // The user may still have a valid refresh token in their cookies. Attempt to\n // initiate a fresh session through the backend using that refresh token.\n //\n // We can still try to refresh even if client requested instant popup.\n // With instant popup option, the client is responsible for providing the user login prompt modal window.\n // If control flow executes this code and client requested instant popup, it means that\n // must have clicked sign in on the login prompt. The browser allows asynchronous code to open a popup\n // if it is caused by a user interaction, clicking on a sign-in button, for example.\n if (!alreadyTriedToRefreshSession) {\n try {\n const newSession = await this.collapsedSessionRefresh(options.scopes);\n this.currentSession = newSession;\n // The session might not have the scopes requested so go back and check again\n return this.getSession(options);\n } catch {\n this.removeLocalSession();\n // If the refresh attempt fails we assume we don't have a session, so continue to create one.\n }\n }\n\n // If we continue here we will show a popup, so exit if this is an optional session request.\n if (options.optional) {\n return undefined;\n }\n\n // We can call authRequester multiple times, the returned session will contain all requested scopes.\n this.currentSession = await this.connector.createSession({\n ...options,\n scopes: this.helper.getExtendedScope(this.currentSession, options.scopes),\n });\n this.stateTracker.setIsSignedIn(true);\n return this.currentSession;\n }\n\n /**\n * Sets `undefined` to this.{@link currentSession} and tells this.{@link stateTracker}, session state tracker,\n * that a user has signed out.\n *\n * Does not propagate session removal to the connector like {@link removeSession}().\n *\n */\n removeLocalSession() {\n this.currentSession = undefined;\n this.stateTracker.setIsSignedIn(false);\n }\n\n async removeSession() {\n this.currentSession = undefined;\n await this.connector.removeSession();\n this.stateTracker.setIsSignedIn(false);\n }\n\n sessionState$() {\n return this.stateTracker.sessionState$();\n }\n\n private async collapsedSessionRefresh(scopes?: Set<string>): Promise<T> {\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.connector.refreshSession({\n scopes: this.helper.getExtendedScope(this.currentSession, scopes),\n });\n\n try {\n const session = await this.refreshPromise;\n if (!this.helper.sessionExistsAndHasScope(session, scopes)) {\n throw new Error(\n 'Refreshed session did not receive the required scopes',\n );\n }\n this.stateTracker.setIsSignedIn(true);\n return session;\n } finally {\n delete this.refreshPromise;\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 { DefaultAuthConnector } from '../../../../lib/AuthConnector';\nimport { RefreshingAuthSessionManager } from '../../../../lib/AuthSessionManager';\nimport { SessionManager } from '../../../../lib/AuthSessionManager/types';\nimport {\n AuthRequestOptions,\n BackstageIdentityApi,\n BackstageIdentityResponse,\n BackstageUserIdentity,\n OAuthApi,\n OpenIdConnectApi,\n ProfileInfo,\n ProfileInfoApi,\n SessionApi,\n SessionState,\n} from '@backstage/core-plugin-api';\nimport { Observable } from '@backstage/types';\nimport {\n OAuth2CreateOptions,\n OAuth2CreateOptionsWithAuthConnector,\n OAuth2Session,\n} from './types';\n\nconst DEFAULT_PROVIDER = {\n id: 'oauth2',\n title: 'Your Identity Provider',\n icon: () => null,\n};\n\nexport type OAuth2Response = {\n providerInfo: {\n accessToken: string;\n idToken: string;\n scope: string;\n expiresInSeconds?: number;\n };\n profile: ProfileInfo;\n backstageIdentity: {\n token: string;\n expiresInSeconds?: number;\n identity: BackstageUserIdentity;\n };\n};\n\n/**\n * Implements a generic OAuth2 flow for auth.\n *\n * @public\n */\nexport default class OAuth2\n implements\n OAuthApi,\n OpenIdConnectApi,\n ProfileInfoApi,\n BackstageIdentityApi,\n SessionApi\n{\n private static createAuthConnector(\n options: OAuth2CreateOptions | OAuth2CreateOptionsWithAuthConnector,\n ) {\n if ('authConnector' in options) {\n return options.authConnector;\n }\n const {\n scopeTransform = x => x,\n configApi,\n discoveryApi,\n environment = 'development',\n provider = DEFAULT_PROVIDER,\n oauthRequestApi,\n popupOptions,\n } = options;\n\n return new DefaultAuthConnector({\n configApi,\n discoveryApi,\n environment,\n provider,\n oauthRequestApi: oauthRequestApi,\n sessionTransform({\n backstageIdentity,\n ...res\n }: OAuth2Response): OAuth2Session {\n const session: OAuth2Session = {\n ...res,\n providerInfo: {\n idToken: res.providerInfo.idToken,\n accessToken: res.providerInfo.accessToken,\n scopes: OAuth2.normalizeScopes(res.providerInfo.scope, {\n scopeTransform,\n }),\n expiresAt: res.providerInfo.expiresInSeconds\n ? new Date(Date.now() + res.providerInfo.expiresInSeconds * 1000)\n : undefined,\n },\n };\n if (backstageIdentity) {\n session.backstageIdentity = {\n token: backstageIdentity.token,\n identity: backstageIdentity.identity,\n expiresAt: backstageIdentity.expiresInSeconds\n ? new Date(Date.now() + backstageIdentity.expiresInSeconds * 1000)\n : undefined,\n };\n }\n return session;\n },\n popupOptions,\n });\n }\n\n static create(\n options: OAuth2CreateOptions | OAuth2CreateOptionsWithAuthConnector,\n ) {\n const { defaultScopes = [], scopeTransform = x => x } = options;\n\n const connector = OAuth2.createAuthConnector(options);\n\n const sessionManager = new RefreshingAuthSessionManager({\n connector,\n defaultScopes: new Set(defaultScopes),\n sessionScopes: (session: OAuth2Session) => session.providerInfo.scopes,\n sessionShouldRefresh: (session: OAuth2Session) => {\n // TODO(Rugvip): Optimize to use separate checks for provider vs backstage session expiration\n let min = Infinity;\n if (session.providerInfo?.expiresAt) {\n min = Math.min(\n min,\n (session.providerInfo.expiresAt.getTime() - Date.now()) / 1000,\n );\n }\n if (session.backstageIdentity?.expiresAt) {\n min = Math.min(\n min,\n (session.backstageIdentity.expiresAt.getTime() - Date.now()) / 1000,\n );\n }\n return min < 60 * 3;\n },\n });\n\n return new OAuth2({ sessionManager, scopeTransform });\n }\n\n private readonly sessionManager: SessionManager<OAuth2Session>;\n private readonly scopeTransform: (scopes: string[]) => string[];\n\n private constructor(options: {\n sessionManager: SessionManager<OAuth2Session>;\n scopeTransform: (scopes: string[]) => string[];\n }) {\n this.sessionManager = options.sessionManager;\n this.scopeTransform = options.scopeTransform;\n }\n\n async signIn() {\n await this.getAccessToken();\n }\n\n async signOut() {\n await this.sessionManager.removeSession();\n }\n\n sessionState$(): Observable<SessionState> {\n return this.sessionManager.sessionState$();\n }\n\n async getAccessToken(\n scope?: string | string[],\n options?: AuthRequestOptions,\n ) {\n const normalizedScopes = OAuth2.normalizeScopes(scope, {\n scopeTransform: this.scopeTransform,\n });\n const session = await this.sessionManager.getSession({\n ...options,\n scopes: normalizedScopes,\n });\n return session?.providerInfo.accessToken ?? '';\n }\n\n async getIdToken(options: AuthRequestOptions = {}) {\n const session = await this.sessionManager.getSession({\n ...options,\n scopes: new Set(['openid']),\n });\n return session?.providerInfo.idToken ?? '';\n }\n\n async getBackstageIdentity(\n options: AuthRequestOptions = {},\n ): Promise<BackstageIdentityResponse | undefined> {\n const session = await this.sessionManager.getSession(options);\n return session?.backstageIdentity;\n }\n\n async getProfile(options: AuthRequestOptions = {}) {\n const session = await this.sessionManager.getSession(options);\n return session?.profile;\n }\n\n /**\n * @public\n */\n public static normalizeScopes(\n scopes?: string | string[],\n options?: { scopeTransform: (scopes: string[]) => string[] },\n ): Set<string> {\n if (!scopes) {\n return new Set();\n }\n\n const scopeList = Array.isArray(scopes)\n ? scopes\n : scopes.split(/[\\s|,]/).filter(Boolean);\n\n const transformedScopes = options\n ? options.scopeTransform(scopeList)\n : scopeList;\n\n return new Set(transformedScopes);\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 { googleAuthApiRef } from '@backstage/core-plugin-api';\nimport { OAuth2 } from '../oauth2';\nimport { OAuthApiCreateOptions } from '../types';\n\nconst DEFAULT_PROVIDER = {\n id: 'google',\n title: 'Google',\n icon: () => null,\n};\n\nconst SCOPE_PREFIX = 'https://www.googleapis.com/auth/';\n\n/**\n * Implements the OAuth flow to Google products.\n *\n * @public\n */\nexport default class GoogleAuth {\n static create(options: OAuthApiCreateOptions): typeof googleAuthApiRef.T {\n const {\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment = 'development',\n provider = DEFAULT_PROVIDER,\n defaultScopes = [\n 'openid',\n `${SCOPE_PREFIX}userinfo.email`,\n `${SCOPE_PREFIX}userinfo.profile`,\n ],\n } = options;\n\n return OAuth2.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n provider,\n environment,\n defaultScopes,\n scopeTransform(scopes: string[]) {\n return scopes.map(scope => {\n if (scope === 'openid') {\n return scope;\n }\n\n if (scope === 'profile' || scope === 'email') {\n return `${SCOPE_PREFIX}userinfo.${scope}`;\n }\n\n if (scope.startsWith(SCOPE_PREFIX)) {\n return scope;\n }\n\n return `${SCOPE_PREFIX}${scope}`;\n });\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 {\n microsoftAuthApiRef,\n AuthRequestOptions,\n AuthProviderInfo,\n ConfigApi,\n DiscoveryApi,\n OAuthRequestApi,\n} from '@backstage/core-plugin-api';\nimport { OAuth2, OAuth2CreateOptions } from '../oauth2';\n\nconst DEFAULT_PROVIDER = {\n id: 'microsoft',\n title: 'Microsoft',\n icon: () => null,\n};\n\n/**\n * Implements the OAuth flow to Microsoft products.\n *\n * @public\n */\nexport default class MicrosoftAuth {\n private oauth2: { [aud: string]: OAuth2 };\n private configApi: ConfigApi | undefined;\n private environment: string;\n private provider: AuthProviderInfo;\n private oauthRequestApi: OAuthRequestApi;\n private discoveryApi: DiscoveryApi;\n private scopeTransform: (scopes: string[]) => string[];\n\n private static MicrosoftGraphID = '00000003-0000-0000-c000-000000000000';\n\n static create(options: OAuth2CreateOptions): typeof microsoftAuthApiRef.T {\n return new MicrosoftAuth(options);\n }\n private constructor(options: OAuth2CreateOptions) {\n const {\n configApi,\n environment = 'development',\n provider = DEFAULT_PROVIDER,\n oauthRequestApi,\n discoveryApi,\n defaultScopes = [\n 'openid',\n 'offline_access',\n 'profile',\n 'email',\n 'User.Read',\n ],\n scopeTransform = scopes => scopes.concat('offline_access'),\n } = options;\n\n this.configApi = configApi;\n this.environment = environment;\n this.provider = provider;\n this.oauthRequestApi = oauthRequestApi;\n this.discoveryApi = discoveryApi;\n this.scopeTransform = scopeTransform;\n\n this.oauth2 = {\n [MicrosoftAuth.MicrosoftGraphID]: OAuth2.create({\n configApi: this.configApi,\n discoveryApi: this.discoveryApi,\n oauthRequestApi: this.oauthRequestApi,\n provider: this.provider,\n environment: this.environment,\n scopeTransform: this.scopeTransform,\n defaultScopes,\n }),\n };\n }\n\n private microsoftGraph(): OAuth2 {\n return this.oauth2[MicrosoftAuth.MicrosoftGraphID];\n }\n\n private static resourceForScopes(scope: string): Promise<string> {\n const audiences = [\n ...new Set(\n scope\n .split(' ')\n .map(MicrosoftAuth.resourceForScope)\n .filter(aud => aud !== 'openid'),\n ),\n ];\n\n if (audiences.length > 1) {\n return Promise.reject(\n new Error(\n `Requested access token with scopes from multiple Azure resources: ${audiences.join(\n ', ',\n )}. Access tokens can only have a single audience.`,\n ),\n );\n }\n const audience = audiences[0] ?? MicrosoftAuth.MicrosoftGraphID;\n return Promise.resolve(audience);\n }\n\n private static resourceForScope(scope: string): string {\n const groups = scope.match(/^(?<resourceURI>.*)\\/(?<scp>[^\\/]*)$/)?.groups;\n if (groups) {\n const { resourceURI } = groups;\n const aud = resourceURI.replace(/^api:\\/\\//, '');\n return aud;\n }\n switch (scope) {\n case 'email':\n case 'openid':\n case 'offline_access':\n case 'profile': {\n return 'openid';\n }\n default:\n return MicrosoftAuth.MicrosoftGraphID;\n }\n }\n\n async getAccessToken(\n scope?: string | string[],\n options?: AuthRequestOptions,\n ): Promise<string> {\n const aud =\n scope === undefined\n ? MicrosoftAuth.MicrosoftGraphID\n : await MicrosoftAuth.resourceForScopes(\n Array.isArray(scope) ? scope.join(' ') : scope,\n );\n if (!(aud in this.oauth2)) {\n this.oauth2[aud] = OAuth2.create({\n configApi: this.configApi,\n discoveryApi: this.discoveryApi,\n oauthRequestApi: this.oauthRequestApi,\n provider: this.provider,\n environment: this.environment,\n scopeTransform: this.scopeTransform,\n });\n }\n return this.oauth2[aud].getAccessToken(scope, options);\n }\n\n getIdToken(options?: AuthRequestOptions) {\n return this.microsoftGraph().getIdToken(options);\n }\n\n getProfile(options?: AuthRequestOptions) {\n return this.microsoftGraph().getProfile(options);\n }\n\n getBackstageIdentity(options?: AuthRequestOptions) {\n return this.microsoftGraph().getBackstageIdentity(options);\n }\n\n signIn() {\n return this.microsoftGraph().signIn();\n }\n\n signOut() {\n return this.microsoftGraph().signOut();\n }\n\n sessionState$() {\n return this.microsoftGraph().sessionState$();\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 { githubAuthApiRef } from '@backstage/core-plugin-api';\nimport { OAuth2 } from '../oauth2';\nimport { OAuthApiCreateOptions } from '../types';\n\nconst DEFAULT_PROVIDER = {\n id: 'github',\n title: 'GitHub',\n icon: () => null,\n};\n\n/**\n * Implements the OAuth flow to GitHub products.\n *\n * @public\n */\nexport default class GithubAuth {\n static create(options: OAuthApiCreateOptions): typeof githubAuthApiRef.T {\n const {\n configApi,\n discoveryApi,\n environment = 'development',\n provider = DEFAULT_PROVIDER,\n oauthRequestApi,\n defaultScopes = ['read:user'],\n } = options;\n\n return OAuth2.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n provider,\n environment,\n defaultScopes,\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 { oktaAuthApiRef } from '@backstage/core-plugin-api';\nimport { OAuth2 } from '../oauth2';\nimport { OAuthApiCreateOptions } from '../types';\n\nconst DEFAULT_PROVIDER = {\n id: 'okta',\n title: 'Okta',\n icon: () => null,\n};\n\nconst OKTA_OIDC_SCOPES: Set<String> = new Set([\n 'openid',\n 'profile',\n 'email',\n 'phone',\n 'address',\n 'groups',\n 'offline_access',\n]);\n\nconst OKTA_SCOPE_PREFIX: string = 'okta.';\n\n/**\n * Implements the OAuth flow to Okta products.\n *\n * @public\n */\nexport default class OktaAuth {\n static create(options: OAuthApiCreateOptions): typeof oktaAuthApiRef.T {\n const {\n configApi,\n discoveryApi,\n environment = 'development',\n provider = DEFAULT_PROVIDER,\n oauthRequestApi,\n defaultScopes = ['openid', 'email', 'profile', 'offline_access'],\n } = options;\n\n return OAuth2.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n provider,\n environment,\n defaultScopes,\n scopeTransform(scopes) {\n return scopes.map(scope => {\n if (OKTA_OIDC_SCOPES.has(scope)) {\n return scope;\n }\n\n if (scope.startsWith(OKTA_SCOPE_PREFIX)) {\n return scope;\n }\n\n return `${OKTA_SCOPE_PREFIX}${scope}`;\n });\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 { gitlabAuthApiRef } from '@backstage/core-plugin-api';\nimport { OAuth2 } from '../oauth2';\nimport { OAuthApiCreateOptions } from '../types';\n\nconst DEFAULT_PROVIDER = {\n id: 'gitlab',\n title: 'GitLab',\n icon: () => null,\n};\n\n/**\n * Implements the OAuth flow to GitLab products.\n *\n * @public\n */\nexport default class GitlabAuth {\n static create(options: OAuthApiCreateOptions): typeof gitlabAuthApiRef.T {\n const {\n configApi,\n discoveryApi,\n environment = 'development',\n provider = DEFAULT_PROVIDER,\n oauthRequestApi,\n defaultScopes = ['read_user'],\n } = options;\n\n return OAuth2.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n provider,\n environment,\n defaultScopes,\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 {\n oneloginAuthApiRef,\n OAuthRequestApi,\n AuthProviderInfo,\n ConfigApi,\n DiscoveryApi,\n} from '@backstage/core-plugin-api';\nimport { OAuth2 } from '../oauth2';\n\n/**\n * OneLogin auth provider create options.\n * @public\n */\nexport type OneLoginAuthCreateOptions = {\n configApi?: ConfigApi;\n discoveryApi: DiscoveryApi;\n oauthRequestApi: OAuthRequestApi;\n environment?: string;\n provider?: AuthProviderInfo;\n};\n\nconst DEFAULT_PROVIDER = {\n id: 'onelogin',\n title: 'onelogin',\n icon: () => null,\n};\n\nconst OIDC_SCOPES: Set<String> = new Set([\n 'openid',\n 'profile',\n 'email',\n 'phone',\n 'address',\n 'groups',\n 'offline_access',\n]);\n\nconst SCOPE_PREFIX: string = 'onelogin.';\n\n/**\n * Implements a OneLogin OAuth flow.\n *\n * @public\n */\nexport default class OneLoginAuth {\n static create(\n options: OneLoginAuthCreateOptions,\n ): typeof oneloginAuthApiRef.T {\n const {\n configApi,\n discoveryApi,\n environment = 'development',\n provider = DEFAULT_PROVIDER,\n oauthRequestApi,\n } = options;\n\n return OAuth2.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n provider,\n environment,\n defaultScopes: ['openid', 'email', 'profile', 'offline_access'],\n scopeTransform(scopes) {\n return scopes.map(scope => {\n if (OIDC_SCOPES.has(scope)) {\n return scope;\n }\n\n if (scope.startsWith(SCOPE_PREFIX)) {\n return scope;\n }\n\n return `${SCOPE_PREFIX}${scope}`;\n });\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 {\n BackstageIdentityResponse,\n bitbucketAuthApiRef,\n ProfileInfo,\n} from '@backstage/core-plugin-api';\n\nimport { OAuthApiCreateOptions } from '../types';\nimport { OAuth2 } from '../oauth2';\n\nexport type BitbucketAuthResponse = {\n providerInfo: {\n accessToken: string;\n scope: string;\n expiresInSeconds: number;\n };\n profile: ProfileInfo;\n backstageIdentity: BackstageIdentityResponse;\n};\n\nconst DEFAULT_PROVIDER = {\n id: 'bitbucket',\n title: 'Bitbucket',\n icon: () => null,\n};\n\n/**\n * Implements the OAuth flow to Bitbucket products.\n *\n * @public\n */\nexport default class BitbucketAuth {\n static create(options: OAuthApiCreateOptions): typeof bitbucketAuthApiRef.T {\n const {\n configApi,\n discoveryApi,\n environment = 'development',\n provider = DEFAULT_PROVIDER,\n oauthRequestApi,\n defaultScopes = ['account'],\n } = options;\n\n return OAuth2.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n provider,\n environment,\n defaultScopes,\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 {\n BackstageIdentityResponse,\n bitbucketServerAuthApiRef,\n ProfileInfo,\n} from '@backstage/core-plugin-api';\n\nimport { OAuthApiCreateOptions } from '../types';\nimport { OAuth2 } from '../oauth2';\n\nexport type BitbucketServerAuthResponse = {\n providerInfo: {\n accessToken: string;\n scope: string;\n expiresInSeconds: number;\n };\n profile: ProfileInfo;\n backstageIdentity: BackstageIdentityResponse;\n};\n\nconst DEFAULT_PROVIDER = {\n id: 'bitbucketServer',\n title: 'Bitbucket Server',\n icon: () => null,\n};\n\n/**\n * Implements the OAuth flow to Bitbucket Server.\n * @public\n */\nexport default class BitbucketServerAuth {\n static create(\n options: OAuthApiCreateOptions,\n ): typeof bitbucketServerAuthApiRef.T {\n const {\n configApi,\n discoveryApi,\n environment = 'development',\n provider = DEFAULT_PROVIDER,\n oauthRequestApi,\n defaultScopes = ['PROJECT_ADMIN'],\n } = options;\n\n return OAuth2.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n provider,\n environment,\n defaultScopes,\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 { atlassianAuthApiRef } from '@backstage/core-plugin-api';\nimport { OAuth2 } from '../oauth2';\nimport { OAuthApiCreateOptions } from '../types';\n\nconst DEFAULT_PROVIDER = {\n id: 'atlassian',\n title: 'Atlassian',\n icon: () => null,\n};\n\n/**\n * Implements the OAuth flow to Atlassian products.\n *\n * @public\n */\nexport default class AtlassianAuth {\n static create(options: OAuthApiCreateOptions): typeof atlassianAuthApiRef.T {\n const {\n configApi,\n discoveryApi,\n environment = 'development',\n provider = DEFAULT_PROVIDER,\n oauthRequestApi,\n } = options;\n\n return OAuth2.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n provider,\n environment,\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 */\nimport { vmwareCloudAuthApiRef } from '@backstage/core-plugin-api';\nimport { OAuth2 } from '../oauth2';\nimport { OAuthApiCreateOptions } from '../types';\n\nconst DEFAULT_PROVIDER = {\n id: 'vmwareCloudServices',\n title: 'VMware Cloud',\n icon: () => null,\n};\n\n/**\n * Implements the OAuth flow for VMware Cloud Services\n *\n * @public\n */\nexport default class VMwareCloudAuth {\n static create(\n options: OAuthApiCreateOptions,\n ): typeof vmwareCloudAuthApiRef.T {\n const {\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment = 'development',\n provider = DEFAULT_PROVIDER,\n defaultScopes = ['openid'],\n } = options;\n\n return OAuth2.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n provider,\n environment,\n defaultScopes,\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 { ApiRef, createApiRef } from '../system';\nimport { JsonValue, Observable } from '@backstage/types';\n\n/**\n * A snapshot in time of the current known value of a storage key.\n *\n * @public\n */\nexport type StorageValueSnapshot<TValue extends JsonValue> =\n | {\n key: string;\n presence: 'unknown' | 'absent';\n value?: undefined;\n }\n | {\n key: string;\n presence: 'present';\n value: TValue;\n };\n\n/**\n * Provides a key-value persistence API.\n *\n * @public\n */\nexport interface StorageApi {\n /**\n * Create a bucket to store data in.\n *\n * @param name - Namespace for the storage to be stored under,\n * will inherit previous namespaces too\n */\n forBucket(name: string): StorageApi;\n\n /**\n * Remove persistent data.\n *\n * @param key - Unique key associated with the data.\n */\n remove(key: string): Promise<void>;\n\n /**\n * Save persistent data, and emit messages to anyone that is using\n * {@link StorageApi.observe$} for this key.\n *\n * @param key - Unique key associated with the data.\n * @param data - The data to be stored under the key.\n */\n set<T extends JsonValue>(key: string, data: T): Promise<void>;\n\n /**\n * Observe the value over time for a particular key in the current bucket.\n *\n * @remarks\n *\n * The observable will only emit values when the value changes in the underlying\n * storage, although multiple values with the same shape may be emitted in a row.\n *\n * If a {@link StorageApi.snapshot} of a key is retrieved and the presence is\n * `'unknown'`, then you are guaranteed to receive a snapshot with a known\n * presence, as long as you observe the key within the same tick.\n *\n * Since the emitted values are shared across all subscribers, it is important\n * not to mutate the returned values. The values may be frozen as a precaution.\n *\n * @param key - Unique key associated with the data\n */\n observe$<T extends JsonValue>(\n key: string,\n ): Observable<StorageValueSnapshot<T>>;\n\n /**\n * Returns an immediate snapshot value for the given key, if possible.\n *\n * @remarks\n *\n * Combine with {@link StorageApi.observe$} to get notified of value changes.\n *\n * Note that this method is synchronous, and some underlying storages may be\n * unable to retrieve a value using this method - the result may or may not\n * consistently have a presence of 'unknown'. Use {@link StorageApi.observe$}\n * to be sure to receive an actual value eventually.\n */\n snapshot<T extends JsonValue>(key: string): StorageValueSnapshot<T>;\n}\n\n/**\n * The {@link ApiRef} of {@link StorageApi}.\n *\n * @public\n */\nexport const storageApiRef: ApiRef<StorageApi> = createApiRef({\n id: 'core.storage',\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 { Observable } from '@backstage/types';\nimport { ApiRef, createApiRef } from '../system';\nimport { AuthProviderInfo } from './auth';\n\n/**\n * Describes how to handle auth requests. Both how to show them to the user, and what to do when\n * the user accesses the auth request.\n *\n * @public\n */\nexport type OAuthRequesterOptions<TOAuthResponse> = {\n /**\n * Information about the auth provider, which will be forwarded to auth requests.\n */\n provider: AuthProviderInfo;\n\n /**\n * Implementation of the auth flow, which will be called synchronously when\n * trigger() is called on an auth requests.\n */\n onAuthRequest(scopes: Set<string>): Promise<TOAuthResponse>;\n};\n\n/**\n * Function used to trigger new auth requests for a set of scopes.\n *\n * @remarks\n *\n * The returned promise will resolve to the same value returned by the onAuthRequest in the\n * {@link OAuthRequesterOptions}. Or rejected, if the request is rejected.\n *\n * This function can be called multiple times before the promise resolves. All calls\n * will be merged into one request, and the scopes forwarded to the onAuthRequest will be the\n * union of all requested scopes.\n *\n * @public\n */\nexport type OAuthRequester<TAuthResponse> = (\n scopes: Set<string>,\n) => Promise<TAuthResponse>;\n\n/**\n * An pending auth request for a single auth provider. The request will remain in this pending\n * state until either reject() or trigger() is called.\n *\n * @remarks\n *\n * Any new requests for the same provider are merged into the existing pending request, meaning\n * there will only ever be a single pending request for a given provider.\n *\n * @public\n */\nexport type PendingOAuthRequest = {\n /**\n * Information about the auth provider, as given in the AuthRequesterOptions\n */\n provider: AuthProviderInfo;\n\n /**\n * Rejects the request, causing all pending AuthRequester calls to fail with \"RejectedError\".\n */\n reject(): void;\n\n /**\n * Trigger the auth request to continue the auth flow, by for example showing a popup.\n *\n * Synchronously calls onAuthRequest with all scope currently in the request.\n */\n trigger(): Promise<void>;\n};\n\n/**\n * Provides helpers for implemented OAuth login flows within Backstage.\n *\n * @public\n */\nexport type OAuthRequestApi = {\n /**\n * A utility for showing login popups or similar things, and merging together multiple requests for\n * different scopes into one request that includes all scopes.\n *\n * The passed in options provide information about the login provider, and how to handle auth requests.\n *\n * The returned AuthRequester function is used to request login with new scopes. These requests\n * are merged together and forwarded to the auth handler, as soon as a consumer of auth requests\n * triggers an auth flow.\n *\n * See AuthRequesterOptions, AuthRequester, and handleAuthRequests for more info.\n */\n createAuthRequester<OAuthResponse>(\n options: OAuthRequesterOptions<OAuthResponse>,\n ): OAuthRequester<OAuthResponse>;\n\n /**\n * Observers pending auth requests. The returned observable will emit all\n * current active auth request, at most one for each created auth requester.\n *\n * Each request has its own info about the login provider, forwarded from the auth requester options.\n *\n * Depending on user interaction, the request should either be rejected, or used to trigger the auth handler.\n * If the request is rejected, all pending AuthRequester calls will fail with a \"RejectedError\".\n * If a auth is triggered, and the auth handler resolves successfully, then all currently pending\n * AuthRequester calls will resolve to the value returned by the onAuthRequest call.\n */\n authRequest$(): Observable<PendingOAuthRequest[]>;\n};\n\n/**\n * The {@link ApiRef} of {@link OAuthRequestApi}.\n *\n * @public\n */\nexport const oauthRequestApiRef: ApiRef<OAuthRequestApi> = createApiRef({\n id: 'core.oauthrequest',\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';\nimport { ResponseError } from '@backstage/errors';\nimport fetch from 'cross-fetch';\nimport * as uuid from 'uuid';\nimport { z } from 'zod';\nimport {\n AuthorizeResult,\n PermissionMessageBatch,\n PermissionCriteria,\n PermissionCondition,\n PermissionEvaluator,\n QueryPermissionRequest,\n AuthorizePermissionRequest,\n AuthorizePermissionResponse,\n QueryPermissionResponse,\n IdentifiedPermissionMessage,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\nimport {\n AuthorizeRequestOptions,\n BasicPermission,\n ResourcePermission,\n} from './types/permission';\nimport { isResourcePermission } from './permissions';\n\nconst permissionCriteriaSchema: z.ZodSchema<\n PermissionCriteria<PermissionCondition>\n> = z.lazy(() =>\n z\n .object({\n rule: z.string(),\n resourceType: z.string(),\n params: z.record(z.any()).optional(),\n })\n .or(z.object({ anyOf: z.array(permissionCriteriaSchema).nonempty() }))\n .or(z.object({ allOf: z.array(permissionCriteriaSchema).nonempty() }))\n .or(z.object({ not: permissionCriteriaSchema })),\n);\n\nconst authorizePermissionResponseSchema: z.ZodSchema<AuthorizePermissionResponse> =\n z.object({\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n });\n\nconst authorizePermissionResponseBatchSchema = z\n .object({\n result: z.array(\n z.union([\n z.literal(AuthorizeResult.ALLOW),\n z.literal(AuthorizeResult.DENY),\n ]),\n ),\n })\n .or(authorizePermissionResponseSchema);\n\nconst queryPermissionResponseSchema: z.ZodSchema<QueryPermissionResponse> =\n z.union([\n z.object({\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n }),\n z.object({\n result: z.literal(AuthorizeResult.CONDITIONAL),\n pluginId: z.string(),\n resourceType: z.string(),\n conditions: permissionCriteriaSchema,\n }),\n ]);\n\nconst responseSchema = <T>(\n itemSchema: z.ZodSchema<T>,\n ids: Set<string>,\n): z.ZodSchema<PermissionMessageBatch<T>> =>\n z.object({\n items: z\n .array(\n z.intersection(\n z.object({\n id: z.string(),\n }),\n itemSchema,\n ),\n )\n .refine(\n items =>\n items.length === ids.size && items.every(({ id }) => ids.has(id)),\n {\n message: 'Items in response do not match request',\n },\n ),\n });\n\n/**\n * Options for {@link PermissionClient} requests.\n *\n * @public\n */\nexport type PermissionClientRequestOptions = {\n token?: string;\n};\n\n/**\n * An isomorphic client for requesting authorization for Backstage permissions.\n * @public\n */\nexport class PermissionClient implements PermissionEvaluator {\n private readonly enabled: boolean;\n private readonly discovery: DiscoveryApi;\n private readonly enableBatchedRequests: boolean;\n\n constructor(options: { discovery: DiscoveryApi; config: Config }) {\n this.discovery = options.discovery;\n this.enabled =\n options.config.getOptionalBoolean('permission.enabled') ?? false;\n\n this.enableBatchedRequests =\n options.config.getOptionalBoolean(\n 'permission.EXPERIMENTAL_enableBatchedRequests',\n ) ?? false;\n }\n\n /**\n * {@inheritdoc PermissionEvaluator.authorize}\n */\n async authorize(\n requests: AuthorizePermissionRequest[],\n options?: PermissionClientRequestOptions,\n ): Promise<AuthorizePermissionResponse[]> {\n if (!this.enabled) {\n return requests.map(_ => ({ result: AuthorizeResult.ALLOW as const }));\n }\n\n if (this.enableBatchedRequests) {\n return this.makeBatchedRequest(requests, options);\n }\n\n return this.makeRequest(\n requests,\n authorizePermissionResponseSchema,\n options,\n );\n }\n\n /**\n * {@inheritdoc PermissionEvaluator.authorizeConditional}\n */\n async authorizeConditional(\n queries: QueryPermissionRequest[],\n options?: PermissionClientRequestOptions,\n ): Promise<QueryPermissionResponse[]> {\n if (!this.enabled) {\n return queries.map(_ => ({ result: AuthorizeResult.ALLOW as const }));\n }\n\n return this.makeRequest(queries, queryPermissionResponseSchema, options);\n }\n\n private async makeRequest<TQuery, TResult>(\n queries: TQuery[],\n itemSchema: z.ZodSchema<TResult>,\n options?: AuthorizeRequestOptions,\n ) {\n const request: PermissionMessageBatch<TQuery> = {\n items: queries.map(query => ({\n id: uuid.v4(),\n ...query,\n })),\n };\n\n const parsedResponse = await this.makeRawRequest(\n request,\n itemSchema,\n options,\n );\n\n const responsesById = parsedResponse.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, z.infer<typeof itemSchema>>);\n\n return request.items.map(query => responsesById[query.id]);\n }\n\n private async makeBatchedRequest(\n queries: AuthorizePermissionRequest[],\n options?: AuthorizeRequestOptions,\n ) {\n const request: Record<string, BatchedAuthorizePermissionRequest> = {};\n\n for (const query of queries) {\n const { permission, resourceRef } = query;\n\n if (isResourcePermission(permission)) {\n request[permission.name] ||= {\n permission,\n resourceRef: [],\n id: uuid.v4(),\n };\n\n if (resourceRef) {\n request[permission.name].resourceRef?.push(resourceRef);\n }\n } else {\n request[permission.name] ||= {\n permission,\n id: uuid.v4(),\n };\n }\n }\n\n const parsedResponse = await this.makeRawRequest(\n { items: Object.values(request) },\n authorizePermissionResponseBatchSchema,\n options,\n );\n\n const responsesById = parsedResponse.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, (typeof parsedResponse)['items'][number]>);\n\n return queries.map(query => {\n const { id } = request[query.permission.name];\n\n const item = responsesById[id];\n\n if (Array.isArray(item.result)) {\n return {\n result: query.resourceRef ? item.result.shift()! : item.result[0],\n };\n }\n return { result: item.result };\n });\n }\n\n private async makeRawRequest<TQuery, TResult>(\n request: PermissionMessageBatch<TQuery>,\n itemSchema: z.ZodSchema<TResult>,\n options?: AuthorizeRequestOptions,\n ) {\n const permissionApi = await this.discovery.getBaseUrl('permission');\n const response = await fetch(`${permissionApi}/authorize`, {\n method: 'POST',\n body: JSON.stringify(request),\n headers: {\n ...this.getAuthorizationHeader(options?.token),\n 'content-type': 'application/json',\n },\n });\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const responseBody = await response.json();\n\n return responseSchema(\n itemSchema,\n new Set(request.items.map(({ id }) => id)),\n ).parse(responseBody);\n }\n\n private getAuthorizationHeader(token?: string): Record<string, string> {\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n}\n\n/**\n * @internal\n */\nexport type BatchedAuthorizePermissionRequest = IdentifiedPermissionMessage<\n | {\n permission: BasicPermission;\n resourceRef?: undefined;\n }\n | { permission: ResourcePermission; resourceRef: string[] }\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 { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api';\nimport { PermissionApi } from './PermissionApi';\nimport {\n AuthorizePermissionRequest,\n AuthorizePermissionResponse,\n PermissionClient,\n} from '@backstage/plugin-permission-common';\nimport { Config } from '@backstage/config';\n\n/**\n * The default implementation of the PermissionApi, which simply calls the authorize method of the given\n * {@link @backstage/plugin-permission-common#PermissionClient}.\n * @public\n */\nexport class IdentityPermissionApi implements PermissionApi {\n private constructor(\n private readonly permissionClient: PermissionClient,\n private readonly identityApi: IdentityApi,\n ) {}\n\n static create(options: {\n config: Config;\n discovery: DiscoveryApi;\n identity: IdentityApi;\n }) {\n const { config, discovery, identity } = options;\n const permissionClient = new PermissionClient({ discovery, config });\n return new IdentityPermissionApi(permissionClient, identity);\n }\n\n async authorize(\n request: AuthorizePermissionRequest,\n ): Promise<AuthorizePermissionResponse> {\n const response = await this.permissionClient.authorize(\n [request],\n await this.identityApi.getCredentials(),\n );\n return response[0];\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 AlertApiForwarder,\n NoOpAnalyticsApi,\n ErrorApiForwarder,\n ErrorAlerter,\n GoogleAuth,\n GithubAuth,\n OktaAuth,\n GitlabAuth,\n MicrosoftAuth,\n BitbucketAuth,\n BitbucketServerAuth,\n OAuthRequestManager,\n WebStorage,\n OneLoginAuth,\n UnhandledErrorForwarder,\n AtlassianAuth,\n createFetchApi,\n FetchMiddlewares,\n VMwareCloudAuth,\n FrontendHostDiscovery,\n} from '@backstage/core-app-api';\n\nimport {\n createApiFactory,\n alertApiRef,\n analyticsApiRef,\n errorApiRef,\n discoveryApiRef,\n fetchApiRef,\n identityApiRef,\n oauthRequestApiRef,\n googleAuthApiRef,\n githubAuthApiRef,\n oktaAuthApiRef,\n gitlabAuthApiRef,\n microsoftAuthApiRef,\n storageApiRef,\n configApiRef,\n oneloginAuthApiRef,\n bitbucketAuthApiRef,\n bitbucketServerAuthApiRef,\n atlassianAuthApiRef,\n vmwareCloudAuthApiRef,\n} from '@backstage/core-plugin-api';\nimport {\n permissionApiRef,\n IdentityPermissionApi,\n} from '@backstage/plugin-permission-react';\n\nexport const apis = [\n createApiFactory({\n api: discoveryApiRef,\n deps: { configApi: configApiRef },\n factory: ({ configApi }) => FrontendHostDiscovery.fromConfig(configApi),\n }),\n createApiFactory({\n api: alertApiRef,\n deps: {},\n factory: () => new AlertApiForwarder(),\n }),\n createApiFactory({\n api: analyticsApiRef,\n deps: {},\n factory: () => new NoOpAnalyticsApi(),\n }),\n createApiFactory({\n api: errorApiRef,\n deps: { alertApi: alertApiRef },\n factory: ({ alertApi }) => {\n const errorApi = new ErrorAlerter(alertApi, new ErrorApiForwarder());\n UnhandledErrorForwarder.forward(errorApi, { hidden: false });\n return errorApi;\n },\n }),\n createApiFactory({\n api: storageApiRef,\n deps: { errorApi: errorApiRef },\n factory: ({ errorApi }) => WebStorage.create({ errorApi }),\n }),\n createApiFactory({\n api: fetchApiRef,\n deps: {\n configApi: configApiRef,\n identityApi: identityApiRef,\n discoveryApi: discoveryApiRef,\n },\n factory: ({ configApi, identityApi, discoveryApi }) => {\n return createFetchApi({\n middleware: [\n FetchMiddlewares.resolvePluginProtocol({\n discoveryApi,\n }),\n FetchMiddlewares.injectIdentityAuth({\n identityApi,\n config: configApi,\n }),\n ],\n });\n },\n }),\n createApiFactory({\n api: oauthRequestApiRef,\n deps: {},\n factory: () => new OAuthRequestManager(),\n }),\n createApiFactory({\n api: googleAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n GoogleAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n createApiFactory({\n api: microsoftAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n MicrosoftAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n createApiFactory({\n api: githubAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n GithubAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n defaultScopes: ['read:user'],\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n createApiFactory({\n api: oktaAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n OktaAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n createApiFactory({\n api: gitlabAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n GitlabAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n createApiFactory({\n api: oneloginAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n OneLoginAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n createApiFactory({\n api: bitbucketAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n BitbucketAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n defaultScopes: ['account'],\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n createApiFactory({\n api: bitbucketServerAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) =>\n BitbucketServerAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n defaultScopes: ['REPO_READ'],\n environment: configApi.getOptionalString('auth.environment'),\n }),\n }),\n createApiFactory({\n api: atlassianAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) => {\n return AtlassianAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n });\n },\n }),\n createApiFactory({\n api: vmwareCloudAuthApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n oauthRequestApi: oauthRequestApiRef,\n configApi: configApiRef,\n },\n factory: ({ discoveryApi, oauthRequestApi, configApi }) => {\n return VMwareCloudAuth.create({\n configApi,\n discoveryApi,\n oauthRequestApi,\n environment: configApi.getOptionalString('auth.environment'),\n });\n },\n }),\n createApiFactory({\n api: permissionApiRef,\n deps: {\n discovery: discoveryApiRef,\n identity: identityApiRef,\n config: configApiRef,\n },\n factory: ({ config, discovery, identity }) =>\n IdentityPermissionApi.create({ config, discovery, identity }),\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 { FetchApi } from '@backstage/core-plugin-api';\nimport { FetchMiddleware } from './types';\n\n/**\n * Builds a fetch API, based on the builtin fetch wrapped by a set of optional\n * middleware implementations that add behaviors.\n *\n * @remarks\n *\n * The middleware are applied in reverse order, i.e. the last one will be\n * \"closest\" to the base implementation. Passing in `[M1, M2, M3]` effectively\n * leads to `M1(M2(M3(baseImplementation)))`.\n *\n * @public\n */\nexport function createFetchApi(options: {\n baseImplementation?: typeof fetch | undefined;\n middleware?: FetchMiddleware | FetchMiddleware[] | undefined;\n}): FetchApi {\n let result = options.baseImplementation || global.fetch;\n\n const middleware = [options.middleware ?? []].flat().reverse();\n for (const m of middleware) {\n result = m.apply(result);\n }\n\n return {\n fetch: result,\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 { IconComponent } from '@backstage/core-plugin-api';\nimport MuiApartmentIcon from '@material-ui/icons/Apartment';\nimport MuiBrokenImageIcon from '@material-ui/icons/BrokenImage';\nimport MuiCategoryIcon from '@material-ui/icons/Category';\nimport MuiCreateNewFolderIcon from '@material-ui/icons/CreateNewFolder';\nimport MuiSubjectIcon from '@material-ui/icons/Subject';\nimport MuiSearchIcon from '@material-ui/icons/Search';\nimport MuiChatIcon from '@material-ui/icons/Chat';\nimport MuiDashboardIcon from '@material-ui/icons/Dashboard';\nimport MuiDocsIcon from '@material-ui/icons/Description';\nimport MuiEmailIcon from '@material-ui/icons/Email';\nimport MuiExtensionIcon from '@material-ui/icons/Extension';\nimport MuiGitHubIcon from '@material-ui/icons/GitHub';\nimport MuiHelpIcon from '@material-ui/icons/Help';\nimport MuiLocationOnIcon from '@material-ui/icons/LocationOn';\nimport MuiMemoryIcon from '@material-ui/icons/Memory';\nimport MuiMenuBookIcon from '@material-ui/icons/MenuBook';\nimport MuiPeopleIcon from '@material-ui/icons/People';\nimport MuiPersonIcon from '@material-ui/icons/Person';\nimport MuiWarningIcon from '@material-ui/icons/Warning';\nimport MuiStorageIcon from '@material-ui/icons/Storage';\nimport MuiFeaturedPlayListIcon from '@material-ui/icons/FeaturedPlayList';\nimport Star from '@material-ui/icons/Star';\nimport StarBorder from '@material-ui/icons/StarBorder';\nimport OpenInNew from '@material-ui/icons/OpenInNew';\n\nexport const icons = {\n brokenImage: MuiBrokenImageIcon as IconComponent,\n // To be confirmed: see https://github.com/backstage/backstage/issues/4970\n catalog: MuiMenuBookIcon as IconComponent,\n scaffolder: MuiCreateNewFolderIcon as IconComponent,\n techdocs: MuiSubjectIcon as IconComponent,\n search: MuiSearchIcon as IconComponent,\n chat: MuiChatIcon as IconComponent,\n dashboard: MuiDashboardIcon as IconComponent,\n docs: MuiDocsIcon as IconComponent,\n email: MuiEmailIcon as IconComponent,\n github: MuiGitHubIcon as IconComponent,\n group: MuiPeopleIcon as IconComponent,\n help: MuiHelpIcon as IconComponent,\n 'kind:api': MuiExtensionIcon as IconComponent,\n 'kind:component': MuiMemoryIcon as IconComponent,\n 'kind:domain': MuiApartmentIcon as IconComponent,\n 'kind:group': MuiPeopleIcon as IconComponent,\n 'kind:location': MuiLocationOnIcon as IconComponent,\n 'kind:system': MuiCategoryIcon as IconComponent,\n 'kind:user': MuiPersonIcon as IconComponent,\n 'kind:resource': MuiStorageIcon as IconComponent,\n 'kind:template': MuiFeaturedPlayListIcon as IconComponent,\n user: MuiPersonIcon as IconComponent,\n warning: MuiWarningIcon as IconComponent,\n star: Star as IconComponent,\n unstarred: StarBorder as IconComponent,\n externalLink: OpenInNew as IconComponent,\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 */\n\nimport { ReactNode, useEffect } from 'react';\nimport CssBaseline from '@material-ui/core/CssBaseline';\nimport {\n ThemeProvider,\n StylesProvider,\n createGenerateClassName,\n Theme as Mui4Theme,\n} from '@material-ui/core/styles';\nimport {\n StyledEngineProvider,\n ThemeProvider as Mui5Provider,\n Theme as Mui5Theme,\n} from '@mui/material/styles';\nimport { UnifiedTheme } from './types';\nimport { unstable_ClassNameGenerator as ClassNameGenerator } from '@mui/material/className';\n\n/**\n * Props for {@link UnifiedThemeProvider}.\n *\n * @public\n */\nexport interface UnifiedThemeProviderProps {\n children: ReactNode;\n theme: UnifiedTheme;\n noCssBaseline?: boolean;\n}\n\n/**\n * This API is introduced in @mui/material (v5.0.5) as a replacement of deprecated createGenerateClassName & only affects v5 Material UI components from `@mui/*`.\n *\n * This call needs to be in the same module as the `UnifiedThemeProvider` to ensure that it doesn't get removed by tree shaking\n */\nClassNameGenerator.configure(componentName => {\n return `v5-${componentName}`;\n});\n\n// Background at https://mui.com/x/migration/migration-data-grid-v4/#using-mui-core-v4-with-v5\n// Rather than disabling globals and custom seed, we instead only set a production prefix that\n// won't collide with Material UI 5 styles. We've already got the separate class name generator\n// for v5 set up in just above, so only the production JSS needs deduplication.\nconst generateV4ClassName = createGenerateClassName({\n productionPrefix: 'jss4-',\n});\n\n/**\n * Provides themes for all Material UI versions supported by the provided unified theme.\n *\n * @public\n */\nexport function UnifiedThemeProvider(\n props: UnifiedThemeProviderProps,\n): JSX.Element {\n const { children, theme, noCssBaseline = false } = props;\n\n const v4Theme = theme.getTheme('v4') as Mui4Theme;\n const v5Theme = theme.getTheme('v5') as Mui5Theme;\n const themeMode = v4Theme ? v4Theme.palette.type : v5Theme?.palette.mode;\n const themeName = 'backstage';\n\n useEffect(() => {\n document.body.setAttribute('data-theme-mode', themeMode);\n document.body.setAttribute('data-theme-name', themeName);\n\n return () => {\n document.body.removeAttribute('data-theme-mode');\n document.body.removeAttribute('data-theme-name');\n };\n }, [themeMode, themeName]);\n\n let cssBaseline: JSX.Element | undefined = undefined;\n if (!noCssBaseline) {\n cssBaseline = <CssBaseline />;\n }\n\n let result = (\n <>\n {cssBaseline}\n {children}\n </>\n );\n\n if (v4Theme) {\n result = (\n <StylesProvider generateClassName={generateV4ClassName}>\n <ThemeProvider theme={v4Theme}>{result}</ThemeProvider>\n </StylesProvider>\n );\n }\n\n if (v5Theme) {\n result = (\n <StyledEngineProvider injectFirst>\n <Mui5Provider theme={v5Theme}>{result}</Mui5Provider>\n </StyledEngineProvider>\n );\n }\n\n return result;\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 { PageTheme } from './types';\n\n/**\n * The default predefined burst shapes.\n *\n * @public\n * @remarks\n *\n * How to add a shape:\n *\n * 1. Get the SVG shape from figma, should be ~1400 wide, ~400 high\n * and only the white-to-transparent mask, no colors.\n * 2. Run it through https://jakearchibald.github.io/svgomg/\n * 3. Run that through https://github.com/tigt/mini-svg-data-uri\n * with something like https://npm.runkit.com/mini-svg-data-uri\n * 4. Wrap the output in `url(\"\")`\n * 5. Give it a name and paste it into the `shapes` object below.\n */\nexport const shapes: Record<string, string> = {\n wave: `url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='1368' height='400' fill='none'%3e%3cmask id='a' width='1368' height='401' x='0' y='0' maskUnits='userSpaceOnUse'%3e%3cpath fill='url(%23paint0_linear)' d='M437 116C223 116 112 0 112 0h1256v400c-82 0-225-21-282-109-112-175-436-175-649-175z'/%3e%3cpath fill='url(%23paint1_linear)' d='M1368 400V282C891-29 788 40 711 161 608 324 121 372 0 361v39h1368z'/%3e%3cpath fill='url(%23paint2_linear)' d='M1368 244v156H0V94c92-24 198-46 375 0l135 41c176 51 195 109 858 109z'/%3e%3cpath fill='url(%23paint3_linear)' d='M1252 400h116c-14-7-35-14-116-16-663-14-837-128-1013-258l-85-61C98 28 46 8 0 0v400h1252z'/%3e%3c/mask%3e%3cg mask='url(%23a)'%3e%3cpath fill='white' d='M-172-98h1671v601H-172z'/%3e%3c/g%3e%3cdefs%3e%3clinearGradient id='paint0_linear' x1='602' x2='1093.5' y1='-960.5' y2='272' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint1_linear' x1='482' x2='480' y1='1058.5' y2='70.5' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint2_linear' x1='424' x2='446.1' y1='-587.5' y2='274.6' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint3_linear' x1='587' x2='349' y1='-1120.5' y2='341' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e\")`,\n wave2: `url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='1368' height='400' fill='none'%3e%3cmask id='a' width='1764' height='479' x='-229' y='-6' maskUnits='userSpaceOnUse'%3e%3cpath fill='url(%23paint0_linear)' d='M0 400h1350C1321 336 525 33 179-2c-345-34-395 236-408 402H0z'/%3e%3cpath fill='url(%23paint1_linear)' d='M1378 177v223H0V217s219 75 327 52C436 246 717-35 965 45s254 144 413 132z'/%3e%3cpath fill='url(%23paint2_linear)' d='M26 400l-78-16c-170 205-44-6-137-30l-4-1 4 1 137 30c37-45 89-110 159-201 399-514-45 238 1176-50 275-65 354-39 91 267H26z'/%3e%3c/mask%3e%3cg mask='url(%23a)'%3e%3cpath fill='white' d='M0 0h1368v400H0z'/%3e%3c/g%3e%3cdefs%3e%3clinearGradient id='paint0_linear' x1='431' x2='397.3' y1='-599' y2='372.8' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint1_linear' x1='236.5' x2='446.6' y1='-586' y2='381.5' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint2_linear' x1='851.8' x2='640.4' y1='-867.2' y2='363.7' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e\")`,\n round: `url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='1368' height='400' fill='none'%3e%3cmask id='a' width='2269' height='1408' x='-610' y='-509' maskUnits='userSpaceOnUse'%3e%3ccircle cx='1212.8' cy='74.8' r='317.5' fill='url(%23paint0_linear)' transform='rotate(-52 1213 75)'/%3e%3ccircle cx='737.8' cy='445.8' r='317.5' fill='url(%23paint1_linear)' transform='rotate(-116 738 446)'/%3e%3ccircle cx='601.8' cy='52.8' r='418.6' fill='url(%23paint2_linear)' transform='rotate(-117 602 53)'/%3e%3ccircle cx='999.8' cy='364' r='389.1' fill='url(%23paint3_linear)' transform='rotate(31 1000 364)'/%3e%3cellipse cx='-109.2' cy='263.5' fill='url(%23paint4_linear)' rx='429.2' ry='465.8' transform='rotate(-85 -109 264)'/%3e%3c/mask%3e%3cg mask='url(%23a)'%3e%3cpath fill='white' d='M0 0h1368v400H0z'/%3e%3c/g%3e%3cdefs%3e%3clinearGradient id='paint0_linear' x1='1301.2' x2='161.4' y1='-1879.7' y2='-969.6' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint1_linear' x1='826.2' x2='-313.6' y1='-1508.7' y2='-598.6' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint2_linear' x1='718.4' x2='-784.3' y1='-2524' y2='-1324.2' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint3_linear' x1='1108.2' x2='-288.6' y1='-2031.1' y2='-915.9' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint4_linear' x1='10.4' x2='-1626.5' y1='-2603.8' y2='-1399.5' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e\")`,\n};\n\n/**\n * The color range variants that are used in e.g. colorful bursts.\n *\n * @public\n */\nexport const colorVariants: Record<string, string[]> = {\n darkGrey: ['#171717', '#383838'],\n marineBlue: ['#006D8F', '#0049A1'],\n veryBlue: ['#0027AF', '#270094'],\n rubyRed: ['#98002B', '#8D1134'],\n toastyOrange: ['#BE2200', '#A41D00'],\n purpleSky: ['#8912CA', '#3E00EA'],\n eveningSea: ['#00CFC5', '#035355'],\n teal: ['#005B4B'],\n pinkSea: ['#C8077A', '#C2297D'],\n greens: ['#4BB8A5', '#187656'],\n};\n\n/**\n * Utility to not have to write colors and shapes twice.\n *\n * @public\n * @remarks\n *\n * As the background shapes and colors are decorative, we place them onto the\n * page as a CSS `background-image` instead of an HTML element of its own.\n */\nexport function genPageTheme(props: {\n colors: string[];\n shape: string;\n options?: {\n fontColor?: string;\n };\n}): PageTheme {\n const { colors, shape, options } = props;\n const gradientColors = colors.length === 1 ? [colors[0], colors[0]] : colors;\n const gradient = `linear-gradient(90deg, ${gradientColors.join(', ')})`;\n const backgroundImage = `${shape}, ${gradient}`;\n const fontColor = options?.fontColor ?? '#FFFFFF';\n\n return {\n colors: colors,\n shape: shape,\n backgroundImage: backgroundImage,\n fontColor: fontColor,\n };\n}\n\n/**\n * All of the builtin page themes.\n *\n * @public\n */\nexport const pageTheme: Record<string, PageTheme> = {\n home: genPageTheme({ colors: colorVariants.teal, shape: shapes.wave }),\n documentation: genPageTheme({\n colors: colorVariants.pinkSea,\n shape: shapes.wave2,\n }),\n tool: genPageTheme({ colors: colorVariants.purpleSky, shape: shapes.round }),\n service: genPageTheme({\n colors: colorVariants.marineBlue,\n shape: shapes.wave,\n }),\n website: genPageTheme({ colors: colorVariants.veryBlue, shape: shapes.wave }),\n library: genPageTheme({ colors: colorVariants.rubyRed, shape: shapes.wave }),\n other: genPageTheme({ colors: colorVariants.darkGrey, shape: shapes.wave }),\n app: genPageTheme({ colors: colorVariants.toastyOrange, shape: shapes.wave }),\n apis: genPageTheme({ colors: colorVariants.teal, shape: shapes.wave2 }),\n card: genPageTheme({ colors: colorVariants.greens, shape: shapes.wave }),\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 */\n\nimport { BackstageTypography, PageTheme, PageThemeSelector } from './types';\nimport { pageTheme as defaultPageThemes } from './pageTheme';\n\nconst DEFAULT_HTML_FONT_SIZE = 16;\nconst DEFAULT_FONT_FAMILY =\n '\"Helvetica Neue\", Helvetica, Roboto, Arial, sans-serif';\nconst DEFAULT_PAGE_THEME = 'home';\n\n/**\n * Default Typography settings.\n *\n * @public\n */\nexport const defaultTypography: BackstageTypography = {\n htmlFontSize: DEFAULT_HTML_FONT_SIZE,\n fontFamily: DEFAULT_FONT_FAMILY,\n h1: {\n fontSize: 54,\n fontWeight: 700,\n marginBottom: 10,\n },\n h2: {\n fontSize: 40,\n fontWeight: 700,\n marginBottom: 8,\n },\n h3: {\n fontSize: 32,\n fontWeight: 700,\n marginBottom: 6,\n },\n h4: {\n fontWeight: 700,\n fontSize: 28,\n marginBottom: 6,\n },\n h5: {\n fontWeight: 700,\n fontSize: 24,\n marginBottom: 4,\n },\n h6: {\n fontWeight: 700,\n fontSize: 20,\n marginBottom: 2,\n },\n};\n\n/**\n * Options for {@link createBaseThemeOptions}.\n *\n * @public\n */\nexport interface BaseThemeOptionsInput<PaletteOptions> {\n palette: PaletteOptions;\n defaultPageTheme?: string;\n pageTheme?: Record<string, PageTheme>;\n fontFamily?: string;\n htmlFontSize?: number;\n typography?: BackstageTypography;\n}\n\n/**\n * A helper for creating theme options.\n *\n * @public\n */\nexport function createBaseThemeOptions<PaletteOptions>(\n options: BaseThemeOptionsInput<PaletteOptions>,\n) {\n const {\n palette,\n htmlFontSize = DEFAULT_HTML_FONT_SIZE,\n fontFamily = DEFAULT_FONT_FAMILY,\n defaultPageTheme = DEFAULT_PAGE_THEME,\n pageTheme = defaultPageThemes,\n typography,\n } = options;\n\n if (!pageTheme[defaultPageTheme]) {\n throw new Error(`${defaultPageTheme} is not defined in pageTheme.`);\n }\n\n defaultTypography.htmlFontSize = htmlFontSize;\n defaultTypography.fontFamily = fontFamily;\n\n return {\n palette,\n typography: typography ?? defaultTypography,\n page: pageTheme[defaultPageTheme],\n getPageTheme: ({ themeId }: PageThemeSelector) =>\n pageTheme[themeId] ?? pageTheme[defaultPageTheme],\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 */\n\nimport { darken, lighten, ThemeOptions } from '@mui/material/styles';\n\n/**\n * A helper for creating theme overrides.\n *\n * @public\n */\nexport const defaultComponentThemes: ThemeOptions['components'] = {\n MuiCssBaseline: {\n styleOverrides: theme => ({\n html: {\n height: '100%',\n fontFamily: theme.typography.fontFamily,\n },\n body: {\n height: '100%',\n fontFamily: theme.typography.fontFamily,\n overscrollBehaviorY: 'none',\n fontSize: '0.875rem',\n lineHeight: 1.43,\n '&::-webkit-scrollbar, & *::-webkit-scrollbar': {\n backgroundColor: theme.palette.background.paper,\n width: '1em',\n },\n '&::-webkit-scrollbar-thumb, & *::-webkit-scrollbar-thumb': {\n borderRadius: 8,\n backgroundColor: theme.palette.textVerySubtle,\n border: `3px solid ${theme.palette.background.paper}`,\n },\n '&::-webkit-scrollbar-thumb:active, & *::-webkit-scrollbar-thumb:active':\n {\n backgroundColor:\n theme.palette.mode === 'dark'\n ? lighten(theme.palette.textVerySubtle, 0.2)\n : darken(theme.palette.textVerySubtle, 0.2),\n },\n '&::-webkit-scrollbar-thumb:hover, & *::-webkit-scrollbar-thumb:hover':\n {\n backgroundColor:\n theme.palette.mode === 'dark'\n ? lighten(theme.palette.textVerySubtle, 0.2)\n : darken(theme.palette.textVerySubtle, 0.2),\n },\n },\n a: {\n color: 'inherit',\n textDecoration: 'none',\n },\n }),\n },\n MuiGrid: {\n defaultProps: {\n spacing: 2,\n },\n },\n MuiSwitch: {\n defaultProps: {\n color: 'primary',\n },\n },\n MuiTableRow: {\n styleOverrides: {\n // Alternating row backgrounds\n root: ({ theme }) => ({\n '&:nth-of-type(odd)': {\n backgroundColor: theme.palette.background.default,\n },\n }),\n // Use pointer for hoverable rows\n hover: {\n '&:hover': {\n cursor: 'pointer',\n },\n },\n // Alternating head backgrounds\n head: ({ theme }) => ({\n '&:nth-of-type(odd)': {\n backgroundColor: theme.palette.background.paper,\n },\n }),\n },\n },\n // Tables are more dense than default mui tables\n MuiTableCell: {\n styleOverrides: {\n root: ({ theme }) => ({\n wordBreak: 'break-word',\n overflow: 'hidden',\n verticalAlign: 'middle',\n lineHeight: '1',\n margin: 0,\n padding: theme.spacing(3, 2, 3, 2.5),\n borderBottom: 0,\n }),\n sizeSmall: ({ theme }) => ({\n padding: theme.spacing(1.5, 2, 1.5, 2.5),\n }),\n head: ({ theme }) => ({\n wordBreak: 'break-word',\n overflow: 'hidden',\n color: theme.palette.textSubtle,\n fontWeight: 'normal',\n lineHeight: '1',\n }),\n },\n },\n MuiTabs: {\n styleOverrides: {\n // Tabs are smaller than default mui tab rows\n root: {\n minHeight: 24,\n },\n },\n },\n MuiTab: {\n styleOverrides: {\n // Tabs are smaller and have a hover background\n root: ({ theme }) => ({\n color: theme.palette.link,\n minHeight: 24,\n textTransform: 'initial',\n letterSpacing: '0.07em',\n '&:hover': {\n color: darken(theme.palette.link, 0.3),\n background: lighten(theme.palette.link, 0.95),\n },\n [theme.breakpoints.up('md')]: {\n minWidth: 120,\n fontSize: theme.typography.pxToRem(14),\n fontWeight: 500,\n },\n }),\n textColorPrimary: ({ theme }) => ({\n color: theme.palette.link,\n }),\n },\n },\n MuiTableSortLabel: {\n styleOverrides: {\n // No color change on hover, just rely on the arrow showing up instead.\n root: {\n color: 'inherit',\n '&:hover': {\n color: 'inherit',\n },\n '&:focus': {\n color: 'inherit',\n },\n // Targets the arrow when the label is focused\n '&:focus svg': {\n opacity: 0.5,\n },\n // Bold font for highlighting selected column\n '&.Mui-active': {\n fontWeight: 'bold',\n color: 'inherit',\n },\n },\n },\n },\n MuiListItemText: {\n styleOverrides: {\n dense: {\n // Default dense list items to adding ellipsis for really long str...\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n },\n },\n },\n MuiButton: {\n styleOverrides: {\n text: {\n // Text buttons have less padding by default, but we want to keep the original padding\n padding: undefined,\n },\n },\n },\n MuiChip: {\n styleOverrides: {\n root: ({ theme }) => ({\n // By default there's no margin, but it's usually wanted, so we add some trailing margin\n marginRight: theme.spacing(1),\n marginBottom: theme.spacing(1),\n }),\n label: ({ theme }) => ({\n lineHeight: theme.spacing(2.5),\n fontWeight: theme.typography.fontWeightMedium,\n fontSize: theme.spacing(1.75),\n }),\n labelSmall: ({ theme }) => ({\n fontSize: theme.spacing(1.5),\n }),\n deleteIcon: ({ theme }) => ({\n width: theme.spacing(3),\n height: theme.spacing(3),\n margin: theme.spacing(0, 0.75, 0, -0.75),\n }),\n deleteIconSmall: ({ theme }) => ({\n width: theme.spacing(2),\n height: theme.spacing(2),\n margin: theme.spacing(0, 0.5, 0, -0.5),\n }),\n },\n },\n MuiCard: {\n styleOverrides: {\n root: {\n // When cards have a forced size, such as when they are arranged in a\n // CSS grid, the content needs to flex such that the actions (buttons\n // etc) end up at the bottom of the card instead of just below the body\n // contents.\n display: 'flex',\n flexDirection: 'column',\n },\n },\n },\n MuiCardHeader: {\n styleOverrides: {\n root: {\n // Reduce padding between header and content\n paddingBottom: 0,\n },\n },\n },\n MuiCardContent: {\n styleOverrides: {\n root: {\n // When cards have a forced size, such as when they are arranged in a\n // CSS grid, the content needs to flex such that the actions (buttons\n // etc) end up at the bottom of the card instead of just below the body\n // contents.\n flexGrow: 1,\n '&:last-child': {\n paddingBottom: undefined,\n },\n },\n },\n },\n MuiCardActions: {\n styleOverrides: {\n root: {\n // We default to putting the card actions at the end\n justifyContent: 'flex-end',\n },\n },\n },\n MuiLink: {\n defaultProps: {\n underline: 'hover',\n },\n },\n MuiPaper: {\n styleOverrides: { root: { backgroundImage: 'unset' } },\n },\n MuiMenuItem: {\n styleOverrides: {\n root: ({ theme }) => ({\n // Fixes a bug with MUI 4 that's fixed in MUI 5\n '&:focus': {\n backgroundColor: theme.palette.action.focus,\n },\n }),\n },\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 */\n\nimport type { Overrides } from '@material-ui/core/styles/overrides';\nimport type { ComponentsProps } from '@material-ui/core/styles/props';\nimport { ComponentsOverrides, Theme, ThemeOptions } from '@mui/material/styles';\nimport { CSSProperties } from 'react';\n\ntype V5Override = ComponentsOverrides[Exclude<\n keyof ComponentsOverrides,\n 'MuiCssBaseline'\n>];\ntype V4Override = Overrides[keyof Overrides];\ntype StaticStyleRules = Record<\n string,\n CSSProperties | Record<string, CSSProperties>\n>;\n\n// Utility function based on v5 `createSpacing`: https://github.com/mui/material-ui/blob/master/packages/mui-system/src/createTheme/createSpacing.ts#L42C3-L59C5\nconst __v5Spacing =\n (defaultSpacing: number) =>\n (...argsInput: ReadonlyArray<number | string>) => {\n const args = argsInput.length === 0 ? [1] : argsInput;\n const transform = (argument: string | number, themeSpacing: number) => {\n if (typeof argument === 'string') {\n return argument;\n }\n return themeSpacing * argument;\n };\n\n return args\n .map(argument => {\n const output = transform(argument, defaultSpacing);\n return typeof output === 'number' ? `${output}px` : output;\n })\n .join(' ');\n };\n\n// Converts callback-based overrides to static styles, e.g.\n// { root: theme => ({ color: theme.color }) } -> { root: { color: 'red' } }\nfunction adaptV5CssBaselineOverride(\n theme: Theme,\n overrides: ComponentsOverrides['MuiCssBaseline'],\n): StaticStyleRules | undefined {\n if (!overrides || typeof overrides === 'string') {\n return undefined;\n }\n\n const styles = typeof overrides === 'function' ? overrides(theme) : overrides;\n if (styles) {\n return { '@global': styles } as StaticStyleRules;\n }\n\n return undefined;\n}\n\n// Converts callback-based overrides to static styles, e.g.\n// { root: theme => ({ color: theme.color }) } -> { root: { color: 'red' } }\nfunction adaptV5Override(\n theme: Theme,\n overrides: V5Override,\n): StaticStyleRules | undefined {\n if (!overrides || typeof overrides === 'string') {\n return undefined;\n }\n if (typeof overrides === 'object') {\n const _theme = { ...theme };\n const defaultSpacing = theme.spacing(1);\n if (typeof defaultSpacing === 'number') {\n // Override potential v4 spacing method: https://mui.com/material-ui/migration/v5-style-changes/#%E2%9C%85-remove-px-suffix\n // `adaptV4Theme as reference: https://github.com/mui/material-ui/blob/v5.x/packages/mui-material/src/styles/adaptV4Theme.js#L54C41-L54C41\n _theme.spacing = __v5Spacing(defaultSpacing);\n }\n return Object.fromEntries(\n Object.entries(overrides).map(([className, style]) => {\n if (typeof style === 'function') {\n return [className, style({ theme: _theme })];\n }\n return [className, style];\n }),\n );\n }\n return overrides as StaticStyleRules;\n}\n\nconst stateStyleKeyPattern = /^&.Mui-([\\w-]+)$/;\n\n// Move state style overrides to the top level, e.g.\n// { root: { '&.Mui-active': { color: 'red' } } } -> { active: { color: 'red' } }\nfunction extractV5StateOverrides(\n overrides: StaticStyleRules | undefined,\n): StaticStyleRules | undefined {\n let output = overrides;\n if (!overrides || typeof overrides !== 'object') {\n return output;\n }\n for (const className of Object.keys(overrides)) {\n const styles = overrides[className];\n if (!styles || typeof styles !== 'object') {\n continue;\n }\n for (const _styleKey of Object.keys(styles)) {\n const styleKey = _styleKey as keyof typeof styles;\n const match = styleKey.match(stateStyleKeyPattern);\n if (match) {\n const [, state] = match;\n const { [styleKey]: stateStyles, ...restStyles } = styles;\n if (stateStyles) {\n output = {\n ...output,\n [className]: restStyles,\n [state]: stateStyles,\n };\n }\n }\n }\n }\n return output;\n}\n\n/**\n * Transform Material UI v5 component themes into a v4 theme props and overrides.\n *\n * @public\n */\nexport function transformV5ComponentThemesToV4(\n theme: Theme,\n components: ThemeOptions['components'] = {},\n): { overrides: Overrides; props: ComponentsProps } {\n const overrides: Record<string, V4Override> = {};\n const props: Record<string, ComponentsProps[keyof ComponentsProps]> = {};\n\n for (const name of Object.keys(components)) {\n const component = components[name as keyof typeof components];\n if (!component) {\n continue;\n }\n if ('styleOverrides' in component) {\n if (name === 'MuiCssBaseline') {\n overrides[name] = adaptV5CssBaselineOverride(\n theme,\n component.styleOverrides as ComponentsOverrides['MuiCssBaseline'],\n );\n } else {\n overrides[name] = extractV5StateOverrides(\n adaptV5Override(theme, component.styleOverrides as V5Override),\n );\n }\n }\n if ('defaultProps' in component) {\n props[name] = component.defaultProps;\n }\n }\n\n return { overrides, props };\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 */\n\nimport {\n Theme as Mui4Theme,\n ThemeOptions as ThemeOptionsV4,\n createTheme,\n} from '@material-ui/core/styles';\nimport type { PaletteOptions as PaletteOptionsV4 } from '@material-ui/core/styles/createPalette';\nimport {\n DeprecatedThemeOptions,\n Theme as Mui5Theme,\n PaletteOptions as PaletteOptionsV5,\n ThemeOptions as ThemeOptionsV5,\n adaptV4Theme,\n createTheme as createV5Theme,\n} from '@mui/material/styles';\nimport { createBaseThemeOptions } from '../base/createBaseThemeOptions';\nimport { BackstageTypography, PageTheme } from '../base/types';\nimport { defaultComponentThemes } from '../v5';\nimport { transformV5ComponentThemesToV4 } from './overrides';\nimport { SupportedThemes, SupportedVersions, UnifiedTheme } from './types';\n\nexport class UnifiedThemeHolder implements UnifiedTheme {\n #themes = new Map<SupportedVersions, SupportedThemes>();\n\n constructor(v4?: Mui4Theme, v5?: Mui5Theme) {\n this.#themes = new Map();\n if (v4) {\n this.#themes.set('v4', v4);\n }\n if (v5) {\n this.#themes.set('v5', v5);\n }\n }\n\n getTheme(version: SupportedVersions): SupportedThemes | undefined {\n return this.#themes.get(version);\n }\n}\n\n/**\n * Options for creating a new {@link UnifiedTheme}.\n *\n * @public\n */\nexport interface UnifiedThemeOptions {\n palette: PaletteOptionsV4 & PaletteOptionsV5;\n defaultPageTheme?: string;\n pageTheme?: Record<string, PageTheme>;\n fontFamily?: string;\n htmlFontSize?: number;\n components?: ThemeOptionsV5['components'];\n typography?: BackstageTypography;\n}\n\n/**\n * Creates a new {@link UnifiedTheme} using the provided options.\n *\n * @public\n */\nexport function createUnifiedTheme(options: UnifiedThemeOptions): UnifiedTheme {\n const themeOptions = createBaseThemeOptions(options);\n const components = { ...defaultComponentThemes, ...options.components };\n const v5Theme = createV5Theme({ ...themeOptions, components });\n\n const v4Overrides = transformV5ComponentThemesToV4(v5Theme, components);\n const v4Theme = { ...createTheme(themeOptions), ...v4Overrides };\n return new UnifiedThemeHolder(v4Theme, v5Theme);\n}\n\n/**\n * Creates a new {@link UnifiedTheme} using Material UI v4 theme options.\n * Note that this uses `adaptV4Theme` from Material UI v5, which is deprecated.\n *\n * @public\n */\nexport function createUnifiedThemeFromV4(\n options: ThemeOptionsV4,\n): UnifiedTheme {\n const v5Theme = adaptV4Theme(options as DeprecatedThemeOptions);\n const v4Theme = createTheme(options);\n return new UnifiedThemeHolder(v4Theme, createV5Theme(v5Theme));\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 */\n\nimport { palettes } from '../base';\nimport { createUnifiedTheme } from './UnifiedTheme';\n\n/**\n * Built-in Backstage Material UI themes.\n *\n * @public\n */\nexport const themes = {\n light: createUnifiedTheme({ palette: palettes.light }),\n dark: createUnifiedTheme({ palette: palettes.dark }),\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\n/**\n * Built-in Backstage color palettes.\n *\n * @public\n */\nexport const palettes = {\n light: {\n type: 'light' as const,\n mode: 'light' as const,\n background: {\n default: '#F8F8F8',\n paper: '#FFFFFF',\n },\n status: {\n ok: '#1DB954',\n warning: '#FF9800',\n error: '#E22134',\n running: '#1F5493',\n pending: '#FFED51',\n aborted: '#757575',\n },\n bursts: {\n fontColor: '#FEFEFE',\n slackChannelText: '#ddd',\n backgroundColor: {\n default: '#7C3699',\n },\n gradient: {\n linear: 'linear-gradient(-137deg, #4BB8A5 0%, #187656 100%)',\n },\n },\n primary: {\n main: '#1F5493',\n },\n banner: {\n info: '#2E77D0',\n error: '#E22134',\n text: '#FFFFFF',\n link: '#000000',\n closeButtonColor: '#FFFFFF',\n warning: '#FF9800',\n },\n border: '#E6E6E6',\n textContrast: '#000000',\n textVerySubtle: '#DDD',\n textSubtle: '#6E6E6E',\n highlight: '#FFFBCC',\n errorBackground: '#FFEBEE',\n warningBackground: '#F59B23',\n infoBackground: '#ebf5ff',\n errorText: '#CA001B',\n infoText: '#004e8a',\n warningText: '#000000',\n linkHover: '#2196F3',\n link: '#0A6EBE',\n gold: '#FFD600',\n navigation: {\n background: '#171717',\n indicator: '#9BF0E1',\n color: '#b5b5b5',\n selectedColor: '#FFF',\n navItem: {\n hoverBackground: '#404040',\n },\n submenu: {\n background: '#404040',\n },\n },\n pinSidebarButton: {\n icon: '#181818',\n background: '#BDBDBD',\n },\n tabbar: {\n indicator: '#9BF0E1',\n },\n },\n dark: {\n type: 'dark' as const,\n mode: 'dark' as const,\n background: {\n default: '#333333',\n paper: '#424242',\n },\n status: {\n ok: '#71CF88',\n warning: '#FFB84D',\n error: '#F84C55',\n running: '#3488E3',\n pending: '#FEF071',\n aborted: '#9E9E9E',\n },\n bursts: {\n fontColor: '#FEFEFE',\n slackChannelText: '#ddd',\n backgroundColor: {\n default: '#7C3699',\n },\n gradient: {\n linear: 'linear-gradient(-137deg, #4BB8A5 0%, #187656 100%)',\n },\n },\n primary: {\n main: '#9CC9FF',\n dark: '#82BAFD',\n },\n secondary: {\n main: '#FF88B2',\n },\n banner: {\n info: '#2E77D0',\n error: '#E22134',\n text: '#FFFFFF',\n link: '#000000',\n closeButtonColor: '#FFFFFF',\n warning: '#FF9800',\n },\n border: '#E6E6E6',\n textContrast: '#FFFFFF',\n textVerySubtle: '#727272',\n textSubtle: '#CCCCCC',\n highlight: '#FFFBCC',\n errorBackground: '#FFEBEE',\n warningBackground: '#F59B23',\n infoBackground: '#ebf5ff',\n errorText: '#CA001B',\n infoText: '#004e8a',\n warningText: '#000000',\n linkHover: '#82BAFD',\n link: '#9CC9FF',\n gold: '#FFD600',\n navigation: {\n background: '#424242',\n indicator: '#9BF0E1',\n color: '#b5b5b5',\n selectedColor: '#FFF',\n navItem: {\n hoverBackground: '#404040',\n },\n submenu: {\n background: '#404040',\n },\n },\n pinSidebarButton: {\n icon: '#404040',\n background: '#BDBDBD',\n },\n tabbar: {\n indicator: '#9BF0E1',\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 UnifiedThemeProvider,\n themes as builtinThemes,\n} from '@backstage/theme';\nimport DarkIcon from '@material-ui/icons/Brightness2';\nimport LightIcon from '@material-ui/icons/WbSunny';\nimport { AppTheme } from '@backstage/core-plugin-api';\n\nexport const themes: AppTheme[] = [\n {\n id: 'light',\n title: 'Light Theme',\n variant: 'light',\n icon: <LightIcon />,\n Provider: ({ children }) => (\n <UnifiedThemeProvider theme={builtinThemes.light} children={children} />\n ),\n },\n {\n id: 'dark',\n title: 'Dark Theme',\n variant: 'dark',\n icon: <DarkIcon />,\n Provider: ({ children }) => (\n <UnifiedThemeProvider theme={builtinThemes.dark} children={children} />\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 { ApiRef, ApiHolder } from '@backstage/core-plugin-api';\n\n/**\n * An ApiHolder that queries multiple other holders from for\n * an Api implementation, returning the first one encountered..\n */\nexport class ApiAggregator implements ApiHolder {\n private readonly holders: ApiHolder[];\n\n constructor(...holders: ApiHolder[]) {\n this.holders = holders;\n }\n\n get<T>(apiRef: ApiRef<T>): T | undefined {\n for (const holder of this.holders) {\n const api = holder.get(apiRef);\n if (api) {\n return api;\n }\n }\n return undefined;\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 { useContext, ReactNode, PropsWithChildren } from 'react';\nimport PropTypes from 'prop-types';\nimport { ApiHolder } from '@backstage/core-plugin-api';\nimport { ApiAggregator } from './ApiAggregator';\nimport {\n createVersionedValueMap,\n createVersionedContext,\n} from '@backstage/version-bridge';\n\n/**\n * Prop types for the ApiProvider component.\n * @public\n */\nexport type ApiProviderProps = {\n apis: ApiHolder;\n children: ReactNode;\n};\n\nconst ApiContext = createVersionedContext<{ 1: ApiHolder }>('api-context');\n\n/**\n * Provides an {@link @backstage/core-plugin-api#ApiHolder} for consumption in\n * the React tree.\n *\n * @public\n */\nexport const ApiProvider = (props: PropsWithChildren<ApiProviderProps>) => {\n const { apis, children } = props;\n const parentHolder = useContext(ApiContext)?.atVersion(1);\n const holder = parentHolder ? new ApiAggregator(apis, parentHolder) : apis;\n\n return (\n <ApiContext.Provider\n value={createVersionedValueMap({ 1: holder })}\n children={children}\n />\n );\n};\n\nApiProvider.propTypes = {\n apis: PropTypes.shape({ get: PropTypes.func.isRequired }).isRequired,\n children: PropTypes.node,\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 { JsonValue, JsonObject } from '@backstage/types';\nimport { AppConfig, Config } from './types';\n\n// Update the same pattern in config-loader package if this is changed\nconst CONFIG_KEY_PART_PATTERN = /^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$/i;\n\nfunction isObject(value: JsonValue | undefined): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction cloneDeep(value: JsonValue | null | undefined): JsonValue | undefined {\n if (typeof value !== 'object' || value === null) {\n return value;\n }\n if (Array.isArray(value)) {\n return value.map(cloneDeep) as JsonValue;\n }\n return Object.fromEntries(\n Object.entries(value).map(([k, v]) => [k, cloneDeep(v)]),\n );\n}\n\nfunction merge(\n into: JsonValue | undefined,\n from?: JsonValue | undefined,\n): JsonValue | undefined {\n if (into === null) {\n return undefined;\n }\n if (into === undefined) {\n return from === undefined ? undefined : merge(from);\n }\n if (typeof into !== 'object' || Array.isArray(into)) {\n return into;\n }\n const fromObj = isObject(from) ? from : {};\n\n const out: JsonObject = {};\n for (const key of new Set([...Object.keys(into), ...Object.keys(fromObj)])) {\n const val = merge(into[key], fromObj[key]);\n if (val !== undefined) {\n out[key] = val;\n }\n }\n return out;\n}\n\nfunction typeOf(value: JsonValue | undefined): string {\n if (value === null) {\n return 'null';\n } else if (Array.isArray(value)) {\n return 'array';\n }\n const type = typeof value;\n if (type === 'number' && isNaN(value as number)) {\n return 'nan';\n }\n if (type === 'string' && value === '') {\n return 'empty-string';\n }\n return type;\n}\n\n// Separate out a couple of common error messages to reduce bundle size.\nconst errors = {\n type(key: string, context: string, typeName: string, expected: string) {\n return `Invalid type in config for key '${key}' in '${context}', got ${typeName}, wanted ${expected}`;\n },\n missing(key: string, context: string) {\n return `Missing required config value at '${key}' in '${context}'`;\n },\n convert(key: string, context: string, expected: string) {\n return `Unable to convert config value for key '${key}' in '${context}' to a ${expected}`;\n },\n};\n\n/**\n * An implementation of the `Config` interface that uses a plain JavaScript object\n * for the backing data, with the ability of linking multiple readers together.\n *\n * @public\n */\nexport class ConfigReader implements Config {\n /**\n * A set of key paths that where removed from the config due to not being visible.\n *\n * This was added as a mutable private member to avoid changes to the public API.\n * Its only purpose of this is to warn users of missing visibility when running\n * the frontend in development mode.\n */\n private filteredKeys?: string[];\n private notifiedFilteredKeys = new Set<string>();\n\n /**\n * Instantiates the config reader from a list of application config objects.\n */\n static fromConfigs(configs: AppConfig[]): ConfigReader {\n if (configs.length === 0) {\n return new ConfigReader(undefined);\n }\n\n // Merge together all configs into a single config with recursive fallback\n // readers, giving the first config object in the array the lowest priority.\n return configs.reduce<ConfigReader>(\n (previousReader, { data, context, filteredKeys, deprecatedKeys }) => {\n const reader = new ConfigReader(data, context, previousReader);\n reader.filteredKeys = filteredKeys;\n\n if (deprecatedKeys) {\n for (const { key, description } of deprecatedKeys) {\n // eslint-disable-next-line no-console\n console.warn(\n `The configuration key '${key}' of ${context} is deprecated and may be removed soon. ${\n description || ''\n }`,\n );\n }\n }\n\n return reader;\n },\n undefined!,\n );\n }\n\n constructor(\n private readonly data: JsonObject | undefined,\n private readonly context: string = 'mock-config',\n private readonly fallback?: ConfigReader,\n private readonly prefix: string = '',\n ) {}\n\n /** {@inheritdoc Config.has} */\n has(key: string): boolean {\n const value = this.readValue(key);\n if (value === null) {\n return false;\n }\n if (value !== undefined) {\n return true;\n }\n return this.fallback?.has(key) ?? false;\n }\n\n /** {@inheritdoc Config.keys} */\n keys(): string[] {\n const localKeys = this.data ? Object.keys(this.data) : [];\n const fallbackKeys = this.fallback?.keys() ?? [];\n return [...new Set([...localKeys, ...fallbackKeys])].filter(\n k => this.data?.[k] !== null,\n );\n }\n\n /** {@inheritdoc Config.get} */\n get<T = JsonValue>(key?: string): T {\n const value = this.getOptional(key);\n if (value === undefined) {\n throw new Error(errors.missing(this.fullKey(key ?? ''), this.context));\n }\n return value as T;\n }\n\n /** {@inheritdoc Config.getOptional} */\n getOptional<T = JsonValue>(key?: string): T | undefined {\n const value = cloneDeep(this.readValue(key));\n const fallbackValue = this.fallback?.getOptional(key);\n\n if (value === null) {\n return undefined;\n }\n if (value === undefined) {\n if (process.env.NODE_ENV === 'development') {\n if (fallbackValue === undefined && key) {\n const fullKey = this.fullKey(key);\n if (\n this.filteredKeys?.includes(fullKey) &&\n !this.notifiedFilteredKeys.has(fullKey)\n ) {\n this.notifiedFilteredKeys.add(fullKey);\n // eslint-disable-next-line no-console\n console.warn(\n `Failed to read configuration value at '${fullKey}' as it is not visible. ` +\n 'See https://backstage.io/docs/conf/defining#visibility for instructions on how to make it visible.',\n );\n }\n }\n }\n return merge(fallbackValue) as T;\n } else if (fallbackValue === undefined) {\n return merge(value) as T;\n }\n\n return merge(value, fallbackValue) as T;\n }\n\n /** {@inheritdoc Config.getConfig} */\n getConfig(key: string): ConfigReader {\n const value = this.getOptionalConfig(key);\n if (value === undefined) {\n throw new Error(errors.missing(this.fullKey(key), this.context));\n }\n return value;\n }\n\n /** {@inheritdoc Config.getOptionalConfig} */\n getOptionalConfig(key: string): ConfigReader | undefined {\n const value = this.readValue(key);\n const fallbackConfig = this.fallback?.getOptionalConfig(key);\n\n if (isObject(value)) {\n return this.copy(value, key, fallbackConfig);\n }\n if (value === null) {\n return undefined;\n }\n if (value !== undefined) {\n throw new TypeError(\n errors.type(this.fullKey(key), this.context, typeOf(value), 'object'),\n );\n }\n return fallbackConfig;\n }\n\n /** {@inheritdoc Config.getConfigArray} */\n getConfigArray(key: string): ConfigReader[] {\n const value = this.getOptionalConfigArray(key);\n if (value === undefined) {\n throw new Error(errors.missing(this.fullKey(key), this.context));\n }\n return value;\n }\n\n /** {@inheritdoc Config.getOptionalConfigArray} */\n getOptionalConfigArray(key: string): ConfigReader[] | undefined {\n const configs = this.readConfigValue<JsonObject[]>(key, values => {\n if (!Array.isArray(values)) {\n return { expected: 'object-array' };\n }\n\n for (const [index, value] of values.entries()) {\n if (!isObject(value)) {\n return { expected: 'object-array', value, key: `${key}[${index}]` };\n }\n }\n return true;\n });\n\n if (!configs) {\n if (process.env.NODE_ENV === 'development') {\n const fullKey = this.fullKey(key);\n if (\n this.filteredKeys?.some(k => k.startsWith(fullKey)) &&\n !this.notifiedFilteredKeys.has(key)\n ) {\n this.notifiedFilteredKeys.add(key);\n // eslint-disable-next-line no-console\n console.warn(\n `Failed to read configuration array at '${key}' as it does not have any visible elements. ` +\n 'See https://backstage.io/docs/conf/defining#visibility for instructions on how to make it visible.',\n );\n }\n }\n return undefined;\n }\n\n return configs.map((obj, index) => this.copy(obj, `${key}[${index}]`));\n }\n\n /** {@inheritdoc Config.getNumber} */\n getNumber(key: string): number {\n const value = this.getOptionalNumber(key);\n if (value === undefined) {\n throw new Error(errors.missing(this.fullKey(key), this.context));\n }\n return value;\n }\n\n /** {@inheritdoc Config.getOptionalNumber} */\n getOptionalNumber(key: string): number | undefined {\n const value = this.readConfigValue<string | number>(\n key,\n val =>\n typeof val === 'number' ||\n typeof val === 'string' || { expected: 'number' },\n );\n if (typeof value === 'number' || value === undefined) {\n return value;\n }\n const number = Number(value);\n if (!Number.isFinite(number)) {\n throw new Error(\n errors.convert(this.fullKey(key), this.context, 'number'),\n );\n }\n return number;\n }\n\n /** {@inheritdoc Config.getBoolean} */\n getBoolean(key: string): boolean {\n const value = this.getOptionalBoolean(key);\n if (value === undefined) {\n throw new Error(errors.missing(this.fullKey(key), this.context));\n }\n return value;\n }\n\n /** {@inheritdoc Config.getOptionalBoolean} */\n getOptionalBoolean(key: string): boolean | undefined {\n const value = this.readConfigValue<string | number | boolean>(\n key,\n val =>\n typeof val === 'boolean' ||\n typeof val === 'number' ||\n typeof val === 'string' || { expected: 'boolean' },\n );\n if (typeof value === 'boolean' || value === undefined) {\n return value;\n }\n const valueString = String(value).trim();\n\n if (/^(?:y|yes|true|1|on)$/i.test(valueString)) {\n return true;\n }\n if (/^(?:n|no|false|0|off)$/i.test(valueString)) {\n return false;\n }\n throw new Error(errors.convert(this.fullKey(key), this.context, 'boolean'));\n }\n\n /** {@inheritdoc Config.getString} */\n getString(key: string): string {\n const value = this.getOptionalString(key);\n if (value === undefined) {\n throw new Error(errors.missing(this.fullKey(key), this.context));\n }\n return value;\n }\n\n /** {@inheritdoc Config.getOptionalString} */\n getOptionalString(key: string): string | undefined {\n return this.readConfigValue(\n key,\n value =>\n (typeof value === 'string' && value !== '') || { expected: 'string' },\n );\n }\n\n /** {@inheritdoc Config.getStringArray} */\n getStringArray(key: string): string[] {\n const value = this.getOptionalStringArray(key);\n if (value === undefined) {\n throw new Error(errors.missing(this.fullKey(key), this.context));\n }\n return value;\n }\n\n /** {@inheritdoc Config.getOptionalStringArray} */\n getOptionalStringArray(key: string): string[] | undefined {\n return this.readConfigValue(key, values => {\n if (!Array.isArray(values)) {\n return { expected: 'string-array' };\n }\n for (const [index, value] of values.entries()) {\n if (typeof value !== 'string' || value === '') {\n return { expected: 'string-array', value, key: `${key}[${index}]` };\n }\n }\n return true;\n });\n }\n\n private fullKey(key: string): string {\n return `${this.prefix}${this.prefix ? '.' : ''}${key}`;\n }\n\n private copy(data: JsonObject, key: string, fallback?: ConfigReader) {\n const reader = new ConfigReader(\n data,\n this.context,\n fallback,\n this.fullKey(key),\n );\n reader.filteredKeys = this.filteredKeys;\n return reader;\n }\n\n private readConfigValue<T extends JsonValue>(\n key: string,\n validate: (\n value: JsonValue,\n ) => { expected: string; value?: JsonValue; key?: string } | true,\n ): T | undefined {\n const value = this.readValue(key);\n\n if (value === undefined) {\n if (process.env.NODE_ENV === 'development') {\n const fullKey = this.fullKey(key);\n if (\n this.filteredKeys?.includes(fullKey) &&\n !this.notifiedFilteredKeys.has(fullKey)\n ) {\n this.notifiedFilteredKeys.add(fullKey);\n // eslint-disable-next-line no-console\n console.warn(\n `Failed to read configuration value at '${fullKey}' as it is not visible. ` +\n 'See https://backstage.io/docs/conf/defining#visibility for instructions on how to make it visible.',\n );\n }\n }\n\n return this.fallback?.readConfigValue(key, validate);\n }\n if (value === null) {\n return undefined;\n }\n const result = validate(value);\n if (result !== true) {\n const { key: keyName = key, value: theValue = value, expected } = result;\n throw new TypeError(\n errors.type(\n this.fullKey(keyName),\n this.context,\n typeOf(theValue),\n expected,\n ),\n );\n }\n\n return value as T;\n }\n\n private readValue(key?: string): JsonValue | undefined {\n const parts = key ? key.split('.') : [];\n for (const part of parts) {\n if (!CONFIG_KEY_PART_PATTERN.test(part)) {\n throw new TypeError(`Invalid config key '${key}'`);\n }\n }\n\n if (this.data === undefined) {\n return undefined;\n }\n\n let value: JsonValue | undefined = this.data;\n for (const [index, part] of parts.entries()) {\n if (isObject(value)) {\n value = value[part];\n } else if (value !== undefined && value !== null) {\n const badKey = this.fullKey(parts.slice(0, index).join('.'));\n throw new TypeError(\n errors.type(badKey, this.context, typeOf(value), 'object'),\n );\n }\n }\n\n return value;\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 { AppThemeApi, AppTheme } from '@backstage/core-plugin-api';\nimport { Observable } from '@backstage/types';\nimport { BehaviorSubject } from '../../../lib/subjects';\n\nconst STORAGE_KEY = 'theme';\n\n/**\n * Exposes the themes installed in the app, and permits switching the currently\n * active theme.\n *\n * @public\n */\nexport class AppThemeSelector implements AppThemeApi {\n static createWithStorage(themes: AppTheme[]) {\n const selector = new AppThemeSelector(themes);\n\n if (!window.localStorage) {\n return selector;\n }\n\n const initialThemeId =\n window.localStorage.getItem(STORAGE_KEY) ?? undefined;\n\n selector.setActiveThemeId(initialThemeId);\n\n selector.activeThemeId$().subscribe(themeId => {\n if (themeId) {\n window.localStorage.setItem(STORAGE_KEY, themeId);\n } else {\n window.localStorage.removeItem(STORAGE_KEY);\n }\n });\n\n window.addEventListener('storage', event => {\n if (event.key === STORAGE_KEY) {\n const themeId = localStorage.getItem(STORAGE_KEY) ?? undefined;\n selector.setActiveThemeId(themeId);\n }\n });\n\n return selector;\n }\n\n private activeThemeId: string | undefined;\n private readonly subject = new BehaviorSubject<string | undefined>(undefined);\n\n constructor(private readonly themes: AppTheme[]) {}\n\n getInstalledThemes(): AppTheme[] {\n return this.themes.slice();\n }\n\n activeThemeId$(): Observable<string | undefined> {\n return this.subject;\n }\n\n getActiveThemeId(): string | undefined {\n return this.activeThemeId;\n }\n\n setActiveThemeId(themeId?: string): void {\n this.activeThemeId = themeId;\n this.subject.next(themeId);\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 FeatureFlagState,\n FeatureFlagsApi,\n FeatureFlag,\n FeatureFlagsSaveOptions,\n} from '@backstage/core-plugin-api';\n\nexport function validateFlagName(name: string): void {\n if (name.length < 3) {\n throw new Error(\n `The '${name}' feature flag must have a minimum length of three characters.`,\n );\n }\n\n if (name.length > 150) {\n throw new Error(\n `The '${name}' feature flag must not exceed 150 characters.`,\n );\n }\n\n if (!name.match(/^[a-z]+[a-z0-9-]+$/)) {\n throw new Error(\n `The '${name}' feature flag must start with a lowercase letter and only contain lowercase letters, numbers and hyphens. ` +\n 'Examples: feature-flag-one, alpha, release-2020',\n );\n }\n}\n\n/**\n * A feature flags implementation that stores the flags in the browser's local\n * storage.\n *\n * @public\n */\nexport class LocalStorageFeatureFlags implements FeatureFlagsApi {\n private registeredFeatureFlags: FeatureFlag[] = [];\n private flags?: Map<string, FeatureFlagState>;\n\n registerFlag(flag: FeatureFlag) {\n validateFlagName(flag.name);\n this.registeredFeatureFlags.push(flag);\n }\n\n getRegisteredFlags(): FeatureFlag[] {\n return this.registeredFeatureFlags.slice();\n }\n\n isActive(name: string): boolean {\n if (!this.flags) {\n this.flags = this.load();\n }\n return this.flags.get(name) === FeatureFlagState.Active;\n }\n\n save(options: FeatureFlagsSaveOptions): void {\n if (!this.flags) {\n this.flags = this.load();\n }\n if (!options.merge) {\n this.flags.clear();\n }\n for (const [name, state] of Object.entries(options.states)) {\n this.flags.set(name, state);\n }\n\n const enabled = Array.from(this.flags.entries()).filter(\n ([, state]) => state === FeatureFlagState.Active,\n );\n window.localStorage.setItem(\n 'featureFlags',\n JSON.stringify(Object.fromEntries(enabled)),\n );\n }\n\n private load(): Map<string, FeatureFlagState> {\n try {\n const jsonStr = window.localStorage.getItem('featureFlags');\n if (!jsonStr) {\n return new Map();\n }\n const json = JSON.parse(jsonStr) as unknown;\n if (typeof json !== 'object' || json === null || Array.isArray(json)) {\n return new Map();\n }\n\n const entries = Object.entries(json).filter(([name, value]) => {\n validateFlagName(name);\n return value === FeatureFlagState.Active;\n });\n\n return new Map(entries);\n } catch {\n return new Map();\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 { ReactNode } from 'react';\nimport { ApiRef, createApiRef } from '../system';\nimport { Observable } from '@backstage/types';\n\n/**\n * Describes a theme provided by the app.\n *\n * @public\n */\nexport type AppTheme = {\n /**\n * ID used to remember theme selections.\n */\n id: string;\n\n /**\n * Title of the theme\n */\n title: string;\n\n /**\n * Theme variant\n */\n variant: 'light' | 'dark';\n\n /**\n * An Icon for the theme mode setting.\n */\n icon?: React.ReactElement;\n\n Provider(props: { children: ReactNode }): JSX.Element | null;\n};\n\n/**\n * The AppThemeApi gives access to the current app theme, and allows switching\n * to other options that have been registered as a part of the App.\n *\n * @public\n */\nexport type AppThemeApi = {\n /**\n * Get a list of available themes.\n */\n getInstalledThemes(): AppTheme[];\n\n /**\n * Observe the currently selected theme. A value of undefined means no specific theme has been selected.\n */\n activeThemeId$(): Observable<string | undefined>;\n\n /**\n * Get the current theme ID. Returns undefined if no specific theme is selected.\n */\n getActiveThemeId(): string | undefined;\n\n /**\n * Set a specific theme to use in the app, overriding the default theme selection.\n *\n * Clear the selection by passing in undefined.\n */\n setActiveThemeId(themeId?: string): void;\n};\n\n/**\n * The {@link ApiRef} of {@link AppThemeApi}.\n *\n * @public\n */\nexport const appThemeApiRef: ApiRef<AppThemeApi> = createApiRef({\n id: 'core.apptheme',\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 { ApiRef, createApiRef } from '@backstage/core-plugin-api';\nimport { Observable } from '@backstage/types';\n\n/** @alpha */\nexport type AppLanguageApi = {\n getAvailableLanguages(): { languages: string[] };\n\n setLanguage(language?: string): void;\n\n getLanguage(): { language: string };\n\n language$(): Observable<{ language: string }>;\n};\n\n/**\n * @alpha\n */\nexport const appLanguageApiRef: ApiRef<AppLanguageApi> = createApiRef({\n id: 'core.applanguage',\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 ApiRef,\n ApiHolder,\n AnyApiRef,\n TypesToApiRefs,\n} from '@backstage/core-plugin-api';\nimport { ApiFactoryHolder } from './types';\n\n/**\n * Handles the actual on-demand instantiation and memoization of APIs out of\n * an {@link ApiFactoryHolder}.\n *\n * @public\n */\nexport class ApiResolver implements ApiHolder {\n /**\n * Validate factories by making sure that each of the apis can be created\n * without hitting any circular dependencies.\n */\n static validateFactories(\n factories: ApiFactoryHolder,\n apis: Iterable<AnyApiRef>,\n ) {\n for (const api of apis) {\n const heap = [api];\n const allDeps = new Set<AnyApiRef>();\n\n while (heap.length) {\n const apiRef = heap.shift()!;\n const factory = factories.get(apiRef);\n if (!factory) {\n continue;\n }\n\n for (const dep of Object.values(factory.deps)) {\n if (dep.id === api.id) {\n throw new Error(`Circular dependency of api factory for ${api}`);\n }\n if (!allDeps.has(dep)) {\n allDeps.add(dep);\n heap.push(dep);\n }\n }\n }\n }\n }\n\n private readonly apis = new Map<string, unknown>();\n\n constructor(private readonly factories: ApiFactoryHolder) {}\n\n get<T>(ref: ApiRef<T>): T | undefined {\n return this.load(ref);\n }\n\n private load<T>(ref: ApiRef<T>, loading: AnyApiRef[] = []): T | undefined {\n const impl = this.apis.get(ref.id);\n if (impl) {\n return impl as T;\n }\n\n const factory = this.factories.get(ref);\n if (!factory) {\n return undefined;\n }\n\n if (loading.includes(factory.api)) {\n throw new Error(`Circular dependency of api factory for ${factory.api}`);\n }\n\n const deps = this.loadDeps(ref, factory.deps, [...loading, factory.api]);\n const api = factory.factory(deps);\n this.apis.set(ref.id, api);\n return api as T;\n }\n\n private loadDeps<T>(\n dependent: ApiRef<unknown>,\n apis: TypesToApiRefs<T>,\n loading: AnyApiRef[],\n ): T {\n const impls = {} as T;\n\n for (const key in apis) {\n if (apis.hasOwnProperty(key)) {\n const ref = apis[key];\n\n const api = this.load(ref, loading);\n if (!api) {\n throw new Error(\n `No API factory available for dependency ${ref} of dependent ${dependent}`,\n );\n }\n impls[key] = api;\n }\n }\n\n return impls;\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 { isValidElement, ReactNode, ReactElement, Children } from 'react';\n\nexport type Discoverer = (element: ReactElement) => ReactNode;\n\nexport type Collector<Result, Context> = () => {\n accumulator: Result;\n visit(\n accumulator: Result,\n element: ReactElement,\n parent: ReactElement | undefined,\n context: Context,\n ): Context;\n};\n\n/**\n * A function that allows you to traverse a tree of React elements using\n * varying methods to discover child nodes and collect data along the way.\n */\nexport function traverseElementTree<Results>(options: {\n root: ReactNode;\n discoverers: Discoverer[];\n collectors: { [name in keyof Results]: Collector<Results[name], any> };\n}): Results {\n const collectors: {\n [name in string]: ReturnType<Collector<any, any>>;\n } = {};\n\n // Bootstrap all collectors, initializing the accumulators and providing the visitor function\n for (const name in options.collectors) {\n if (options.collectors.hasOwnProperty(name)) {\n collectors[name] = options.collectors[name]();\n }\n }\n\n // Internal representation of an element in the tree that we're iterating over\n type QueueItem = {\n node: ReactNode;\n parent: ReactElement | undefined;\n contexts: { [name in string]: unknown };\n };\n\n const queue = [\n {\n node: Children.toArray(options.root),\n parent: undefined,\n contexts: {},\n } as QueueItem,\n ];\n\n while (queue.length !== 0) {\n const { node, parent, contexts } = queue.shift()!;\n\n // While the parent and the element we pass on to collectors and discoverers\n // have been validated and are known to be React elements, the child nodes\n // emitted by the discoverers are not.\n Children.forEach(node, element => {\n if (!isValidElement(element)) {\n return;\n }\n\n const nextContexts: QueueItem['contexts'] = {};\n\n // Collectors populate their result data using the current node, and compute\n // context for the next iteration\n for (const name in collectors) {\n if (collectors.hasOwnProperty(name)) {\n const collector = collectors[name];\n\n nextContexts[name] = collector.visit(\n collector.accumulator,\n element,\n parent,\n contexts[name],\n );\n }\n }\n\n // Discoverers provide ways to continue the traversal from the current element\n for (const discoverer of options.discoverers) {\n const children = discoverer(element);\n if (children) {\n queue.push({\n node: children,\n parent: element,\n contexts: nextContexts,\n });\n }\n }\n });\n }\n\n return Object.fromEntries(\n Object.entries(collectors).map(([name, c]) => [name, c.accumulator]),\n ) as Results;\n}\n\nexport function createCollector<Result, Context>(\n accumulatorFactory: () => Result,\n visit: ReturnType<Collector<Result, Context>>['visit'],\n): Collector<Result, Context> {\n return () => ({ accumulator: accumulatorFactory(), visit });\n}\n\nexport function childDiscoverer(element: ReactElement): ReactNode {\n return element.props?.children;\n}\n\nexport function routeElementDiscoverer(element: ReactElement): ReactNode {\n if (element.props?.path && element.props?.element) {\n return element.props?.element;\n }\n return undefined;\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 { BackstagePlugin, getComponentData } from '@backstage/core-plugin-api';\nimport { createCollector } from '../extensions/traversal';\n\nexport const pluginCollector = createCollector(\n () => new Set<BackstagePlugin>(),\n (acc, node) => {\n const plugin = getComponentData<BackstagePlugin>(node, 'core.plugin');\n if (plugin) {\n acc.add(plugin);\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 featureFlagsApiRef,\n useApi,\n attachComponentData,\n} from '@backstage/core-plugin-api';\nimport { ReactNode } from 'react';\n\n/**\n * Props for the {@link FeatureFlagged} component.\n *\n * @public\n */\nexport type FeatureFlaggedProps = { children: ReactNode } & (\n | { with: string }\n | { without: string }\n);\n\n/**\n * Enables or disables rendering of its children based on the state of a given\n * feature flag.\n *\n * @public\n */\nexport const FeatureFlagged = (props: FeatureFlaggedProps) => {\n const { children } = props;\n const featureFlagApi = useApi(featureFlagsApiRef);\n const isEnabled =\n 'with' in props\n ? featureFlagApi.isActive(props.with)\n : !featureFlagApi.isActive(props.without);\n return <>{isEnabled ? children : null}</>;\n};\n\nattachComponentData(FeatureFlagged, 'core.featureFlagged', true);\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 RouteRef,\n getComponentData,\n BackstagePlugin,\n} from '@backstage/core-plugin-api';\nimport { isValidElement, ReactNode, Children } from 'react';\nimport { BackstageRouteObject } from './types';\nimport { createCollector } from '../extensions/traversal';\nimport { FeatureFlagged, FeatureFlaggedProps } from './FeatureFlagged';\n\n// We always add a child that matches all subroutes but without any route refs. This makes\n// sure that we're always able to match each route no matter how deep the navigation goes.\n// The route resolver then takes care of selecting the most specific match in order to find\n// mount points that are as deep in the routing tree as possible.\nexport const MATCH_ALL_ROUTE: BackstageRouteObject = {\n caseSensitive: false,\n path: '*',\n element: 'match-all', // These elements aren't used, so we add in a bit of debug information\n routeRefs: new Set(),\n plugins: new Set(),\n};\n\nfunction stringifyNode(node: ReactNode): string {\n const anyNode = node as { type?: { displayName?: string; name?: string } };\n if (anyNode?.type) {\n return (\n anyNode.type.displayName ?? anyNode.type.name ?? String(anyNode.type)\n );\n }\n return String(anyNode);\n}\n\nconst pluginSet = (\n plugin: BackstagePlugin | undefined,\n): Set<BackstagePlugin> => {\n const set = new Set<BackstagePlugin>();\n if (plugin) {\n set.add(plugin);\n }\n return set;\n};\n\ninterface RoutingV2CollectorContext {\n routeRef?: RouteRef;\n gatherPath?: string;\n gatherRouteRef?: RouteRef;\n obj?: BackstageRouteObject;\n isElementAncestor?: boolean;\n}\n\n// This collects all the mount points and their plugins within an element tree.\n// Unlike regular traversal this ignores all other things, like path props and mount point gatherers.\nfunction collectSubTree(\n node: ReactNode,\n entries = new Array<{ routeRef: RouteRef; plugin?: BackstagePlugin }>(),\n) {\n Children.forEach(node, element => {\n if (!isValidElement(element)) {\n return;\n }\n\n const routeRef = getComponentData<RouteRef>(element, 'core.mountPoint');\n if (routeRef) {\n const plugin = getComponentData<BackstagePlugin>(element, 'core.plugin');\n entries.push({ routeRef, plugin });\n }\n\n collectSubTree(element.props.children, entries);\n });\n\n return entries;\n}\n\nexport const routingV2Collector = createCollector(\n () => ({\n paths: new Map<RouteRef, string>(),\n parents: new Map<RouteRef, RouteRef | undefined>(),\n objects: new Array<BackstageRouteObject>(),\n }),\n (acc, node, parent, ctx?: RoutingV2CollectorContext) => {\n // If we're in an element prop, ignore everything\n if (ctx?.isElementAncestor) {\n return ctx;\n }\n\n // Start ignoring everything if we enter an element prop\n if (parent?.props.element === node) {\n return { ...ctx, isElementAncestor: true };\n }\n\n const pathProp: unknown = node.props?.path;\n\n const mountPoint = getComponentData<RouteRef>(node, 'core.mountPoint');\n if (mountPoint && pathProp) {\n throw new Error(\n `Path property may not be set directly on a routable extension \"${stringifyNode(\n node,\n )}\"`,\n );\n }\n\n const parentChildren = ctx?.obj?.children ?? acc.objects;\n\n if (pathProp !== undefined) {\n if (typeof pathProp !== 'string') {\n throw new Error(\n `Element path must be a string at \"${stringifyNode(node)}\"`,\n );\n }\n\n const path = pathProp.startsWith('/') ? pathProp.slice(1) : pathProp;\n\n const elementProp = node.props.element;\n\n if (getComponentData<boolean>(node, 'core.gatherMountPoints')) {\n if (elementProp) {\n throw new Error(\n `Mount point gatherers may not have an element prop \"${stringifyNode(\n node,\n )}\"`,\n );\n }\n\n const newObj = {\n path,\n element: 'gathered',\n routeRefs: new Set<RouteRef>(),\n caseSensitive: Boolean(node.props?.caseSensitive),\n children: [MATCH_ALL_ROUTE],\n plugins: new Set<BackstagePlugin>(),\n };\n parentChildren.push(newObj);\n\n return {\n obj: newObj,\n gatherPath: path,\n routeRef: ctx?.routeRef,\n gatherRouteRef: ctx?.routeRef,\n };\n }\n\n if (elementProp) {\n const [extension, ...others] = collectSubTree(elementProp);\n if (others.length > 0) {\n throw new Error(\n `Route element with path \"${pathProp}\" may not contain multiple routable extensions`,\n );\n }\n if (!extension) {\n return ctx;\n }\n const { routeRef, plugin } = extension;\n\n const newObj = {\n path,\n element: 'mounted',\n routeRefs: new Set([routeRef]),\n caseSensitive: Boolean(node.props?.caseSensitive),\n children: [MATCH_ALL_ROUTE],\n plugins: pluginSet(plugin),\n };\n parentChildren.push(newObj);\n acc.paths.set(routeRef, path);\n acc.parents.set(routeRef, ctx?.routeRef);\n\n return {\n obj: newObj,\n routeRef: routeRef ?? ctx?.routeRef,\n gatherPath: path,\n gatherRouteRef: ctx?.gatherRouteRef,\n };\n }\n }\n\n if (mountPoint) {\n if (ctx?.gatherPath === undefined) {\n throw new Error(\n `Routable extension \"${stringifyNode(\n node,\n )}\" with mount point \"${mountPoint}\" must be assigned a path`,\n );\n }\n\n ctx?.obj?.routeRefs.add(mountPoint);\n\n const mountPointPlugin = getComponentData<BackstagePlugin>(\n node,\n 'core.plugin',\n );\n if (mountPointPlugin) {\n ctx?.obj?.plugins.add(mountPointPlugin);\n }\n\n acc.paths.set(mountPoint, ctx.gatherPath);\n acc.parents.set(mountPoint, ctx?.gatherRouteRef);\n\n return {\n ...ctx,\n routeRef: mountPoint,\n };\n }\n\n return ctx;\n },\n);\n\ninterface RoutingV1CollectorContext {\n path?: string;\n routeRef?: RouteRef;\n obj?: BackstageRouteObject;\n sticky?: boolean;\n}\n\n/**\n * This is the old V1 logic for collecting the routing model.\n * It is being replaced by a new collector because this collection\n * logic does not work well beyond react-router v6 beta.\n *\n * The breaking change is that react-router now requires route\n * elements to be `Route` components, and directly renders the\n * element prop rather than the `Route` itself. This means it is\n * no longer possible to create utility route components. In order\n * to fill this gap and in general simplify the route collection\n * logic, a new route collection logic is created.\n *\n * @internal\n */\nexport const routingV1Collector = createCollector(\n () => ({\n paths: new Map<RouteRef, string>(),\n parents: new Map<RouteRef, RouteRef | undefined>(),\n objects: new Array<BackstageRouteObject>(),\n }),\n (acc, node, parent, ctx?: RoutingV1CollectorContext) => {\n // Ignore the top-level element within element props, since it's already been collected.\n if (parent?.props.element === node) {\n return ctx;\n }\n\n let currentObj = ctx?.obj;\n let currentParentRouteRef = ctx?.routeRef;\n let sticky = ctx?.sticky;\n\n const path: string | undefined = node.props?.path;\n const parentChildren = currentObj?.children ?? acc.objects;\n const caseSensitive: boolean = Boolean(node.props?.caseSensitive);\n\n // The context path is used during mount point gathering to assign the same path\n // to all discovered mount points\n let currentCtxPath = ctx?.path;\n\n // Start gathering mount points when we encounter a mount point gathering flag\n if (getComponentData<boolean>(node, 'core.gatherMountPoints')) {\n if (!path) {\n throw new Error('Mount point gatherer must have a path');\n }\n currentCtxPath = path;\n }\n\n // Route refs are discovered on the element itself, and on the top-level\n // element within the element prop if it exists.\n const element = node.props?.element;\n let routeRef = getComponentData<RouteRef>(node, 'core.mountPoint');\n if (!routeRef && isValidElement(element)) {\n routeRef = getComponentData<RouteRef>(element, 'core.mountPoint');\n }\n\n if (routeRef) {\n // First the path gathering\n\n let routePath: string | undefined = path;\n // If we're gathering mount points we use the context path as out path, unless\n // the element has its own path, in which case we use that instead and stop gathering\n if (currentCtxPath) {\n if (routePath) {\n currentCtxPath = undefined;\n } else {\n routePath = currentCtxPath;\n }\n }\n if (!routePath) {\n throw new Error('Mounted routable extension must have a path');\n }\n acc.paths.set(routeRef, routePath);\n\n // Then the parent gathering\n\n // \"sticky\" route ref is when we've encountered a mount point gatherer, and we want a\n // mount points beneath it to have the same parent, regardless of internal structure\n if (currentParentRouteRef && sticky) {\n acc.parents.set(routeRef, currentParentRouteRef);\n\n // When we encounter a mount point with an explicit path, we stop gathering\n // mount points within the children and remove the sticky state\n if (path) {\n currentParentRouteRef = routeRef;\n sticky = false;\n }\n } else {\n acc.parents.set(routeRef, currentParentRouteRef);\n currentParentRouteRef = routeRef;\n }\n\n // Then construct the objects\n\n if (path) {\n currentObj = {\n caseSensitive,\n path,\n element: 'mounted',\n routeRefs: new Set([routeRef]),\n children: [MATCH_ALL_ROUTE],\n plugins: pluginSet(\n getComponentData<BackstagePlugin>(\n node.props.element,\n 'core.plugin',\n ),\n ),\n };\n parentChildren.push(currentObj);\n } else {\n currentObj?.routeRefs.add(routeRef);\n }\n }\n\n if (getComponentData<boolean>(node, 'core.gatherMountPoints')) {\n sticky = true;\n }\n\n const isGatherer = getComponentData<boolean>(\n node,\n 'core.gatherMountPoints',\n );\n if (isGatherer) {\n if (!path) {\n throw new Error('Mount point gatherer must have a path');\n }\n if (!routeRef) {\n currentObj = {\n caseSensitive,\n path,\n element: 'gathered',\n routeRefs: new Set(),\n children: [MATCH_ALL_ROUTE],\n plugins: ctx?.obj?.plugins || new Set(),\n };\n parentChildren.push(currentObj);\n }\n }\n\n return {\n obj: currentObj,\n path: currentCtxPath,\n routeRef: currentParentRouteRef,\n sticky,\n };\n },\n);\n\nexport const featureFlagCollector = createCollector(\n () => new Set<string>(),\n (acc, node) => {\n if (node.type === FeatureFlagged) {\n const props = node.props as FeatureFlaggedProps;\n acc.add('with' in props ? props.with : props.without);\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 {\n RouteRef,\n SubRouteRef,\n ExternalRouteRef,\n BackstagePlugin,\n} from '@backstage/core-plugin-api';\nimport { getOrCreateGlobalSingleton } from '@backstage/version-bridge';\n\ntype RouteRefType = Exclude<\n keyof RouteRef,\n 'params' | 'path' | 'title' | 'icon'\n>;\nexport const routeRefType: RouteRefType = getOrCreateGlobalSingleton<any>(\n 'route-ref-type',\n () => Symbol('route-ref-type'),\n);\n\nexport type AnyParams = { [param in string]: string } | undefined;\n\nexport type AnyRouteRef =\n | RouteRef<any>\n | SubRouteRef<any>\n | ExternalRouteRef<any, any>;\n\n// The extra TS magic here is to require a single params argument if the RouteRef\n// had at least one param defined, but require 0 arguments if there are no params defined.\n// Without this we'd have to pass in empty object to all parameter-less RouteRefs\n// just to make TypeScript happy, or we would have to make the argument optional in\n// which case you might forget to pass it in when it is actually required.\nexport type RouteFunc<Params extends AnyParams> = (\n ...[params]: Params extends undefined ? readonly [] : readonly [Params]\n) => string;\n\n// A duplicate of the react-router RouteObject, but with routeRef added\nexport interface BackstageRouteObject {\n caseSensitive: boolean;\n children?: BackstageRouteObject[];\n element: React.ReactNode;\n path: string;\n routeRefs: Set<RouteRef>;\n plugins: Set<BackstagePlugin>;\n}\n\nexport function isRouteRef<Params extends AnyParams>(\n routeRef:\n | RouteRef<Params>\n | SubRouteRef<Params>\n | ExternalRouteRef<Params, any>,\n): routeRef is RouteRef<Params> {\n return routeRef[routeRefType] === 'absolute';\n}\n\nexport function isSubRouteRef<Params extends AnyParams>(\n routeRef:\n | RouteRef<Params>\n | SubRouteRef<Params>\n | ExternalRouteRef<Params, any>,\n): routeRef is SubRouteRef<Params> {\n return routeRef[routeRefType] === 'sub';\n}\n\nexport function isExternalRouteRef<\n Params extends AnyParams,\n Optional extends boolean,\n>(\n routeRef:\n | RouteRef<Params>\n | SubRouteRef<Params>\n | ExternalRouteRef<Params, Optional>,\n): routeRef is ExternalRouteRef<Params, Optional> {\n return routeRef[routeRefType] === 'external';\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 */\n\n// Joins a list of paths together, avoiding trailing and duplicate slashes\nexport function joinPaths(...paths: string[]): string {\n const normalized = paths.join('/').replace(/\\/\\/+/g, '/');\n if (normalized !== '/' && normalized.endsWith('/')) {\n return normalized.slice(0, -1);\n }\n return normalized;\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 { generatePath, matchRoutes } from 'react-router-dom';\nimport {\n AnyRouteRef,\n BackstageRouteObject,\n AnyParams,\n RouteFunc,\n routeRefType,\n isRouteRef,\n isSubRouteRef,\n isExternalRouteRef,\n} from './types';\nimport {\n RouteRef,\n ExternalRouteRef,\n SubRouteRef,\n} from '@backstage/core-plugin-api';\nimport { joinPaths } from './helpers';\nimport mapValues from 'lodash/mapValues';\n\n/**\n * Resolves the absolute route ref that our target route ref is pointing pointing to, as well\n * as the relative target path.\n *\n * Returns an undefined target ref if one could not be fully resolved.\n */\nfunction resolveTargetRef(\n anyRouteRef: AnyRouteRef,\n routePaths: Map<RouteRef, string>,\n routeBindings: Map<AnyRouteRef, AnyRouteRef | undefined>,\n): readonly [RouteRef | undefined, string] {\n // First we figure out which absolute route ref we're dealing with, an if there was an sub route path to append.\n // For sub routes it will be the parent path, while for external routes it will be the bound route.\n let targetRef: RouteRef;\n let subRoutePath = '';\n if (isRouteRef(anyRouteRef)) {\n targetRef = anyRouteRef;\n } else if (isSubRouteRef(anyRouteRef)) {\n targetRef = anyRouteRef.parent;\n subRoutePath = anyRouteRef.path;\n } else if (isExternalRouteRef(anyRouteRef)) {\n const resolvedRoute = routeBindings.get(anyRouteRef);\n if (!resolvedRoute) {\n return [undefined, ''];\n }\n if (isRouteRef(resolvedRoute)) {\n targetRef = resolvedRoute;\n } else if (isSubRouteRef(resolvedRoute)) {\n targetRef = resolvedRoute.parent;\n subRoutePath = resolvedRoute.path;\n } else {\n throw new Error(\n `ExternalRouteRef was bound to invalid target, ${resolvedRoute}`,\n );\n }\n } else if (anyRouteRef[routeRefType]) {\n throw new Error(\n `Unknown or invalid route ref type, ${anyRouteRef[routeRefType]}`,\n );\n } else {\n throw new Error(`Unknown object passed to useRouteRef, got ${anyRouteRef}`);\n }\n\n // Bail if no absolute path could be resolved\n if (!targetRef) {\n return [undefined, ''];\n }\n\n // Find the path that our target route is bound to\n const resolvedPath = routePaths.get(targetRef);\n if (resolvedPath === undefined) {\n return [undefined, ''];\n }\n\n // SubRouteRefs join the path from the parent route with its own path\n const targetPath = joinPaths(resolvedPath, subRoutePath);\n return [targetRef, targetPath];\n}\n\n/**\n * Resolves the complete base path for navigating to the target RouteRef.\n */\nfunction resolveBasePath(\n targetRef: RouteRef,\n sourceLocation: Parameters<typeof matchRoutes>[1],\n routePaths: Map<RouteRef, string>,\n routeParents: Map<RouteRef, RouteRef | undefined>,\n routeObjects: BackstageRouteObject[],\n) {\n // While traversing the app element tree we build up the routeObjects structure\n // used here. It is the same kind of structure that react-router creates, with the\n // addition that associated route refs are stored throughout the tree. This lets\n // us look up all route refs that can be reached from our source location.\n // Because of the similar route object structure, we can use `matchRoutes` from\n // react-router to do the lookup of our current location.\n const match = matchRoutes(routeObjects, sourceLocation) ?? [];\n\n // While we search for a common routing root between our current location and\n // the target route, we build a list of all route refs we find that we need\n // to traverse to reach the target.\n const refDiffList = Array<RouteRef>();\n\n let matchIndex = -1;\n for (\n let targetSearchRef: RouteRef | undefined = targetRef;\n targetSearchRef;\n targetSearchRef = routeParents.get(targetSearchRef)\n ) {\n // The match contains a list of all ancestral route refs present at our current location\n // Starting at the desired target ref and traversing back through its parents, we search\n // for a target ref that is present in the match for our current location. When a match\n // is found it means we have found a common base to resolve the route from.\n matchIndex = match.findIndex(m =>\n (m.route as BackstageRouteObject).routeRefs.has(targetSearchRef!),\n );\n if (matchIndex !== -1) {\n break;\n }\n\n // Every time we move a step up in the ancestry of the target ref, we add the current ref\n // to the diff list, which ends up being the list of route refs to traverse form the common base\n // in order to reach our target.\n refDiffList.unshift(targetSearchRef);\n }\n\n // If our target route is present in the initial match we need to construct the final path\n // from the parent of the matched route segment. That's to allow the caller of the route\n // function to supply their own params.\n if (refDiffList.length === 0) {\n matchIndex -= 1;\n }\n\n // This is the part of the route tree that the target and source locations have in common.\n // We re-use the existing pathname directly along with all params.\n const parentPath = matchIndex === -1 ? '' : match[matchIndex].pathname;\n\n // This constructs the mid section of the path using paths resolved from all route refs\n // we need to traverse to reach our target except for the very last one. None of these\n // paths are allowed to require any parameters, as the caller would have no way of knowing\n // what parameters those are.\n const diffPaths = refDiffList.slice(0, -1).map(ref => {\n const path = routePaths.get(ref);\n if (path === undefined) {\n throw new Error(`No path for ${ref}`);\n }\n if (path.includes(':')) {\n throw new Error(\n `Cannot route to ${targetRef} with parent ${ref} as it has parameters`,\n );\n }\n return path;\n });\n\n return `${joinPaths(parentPath, ...diffPaths)}/`;\n}\n\nexport class RouteResolver {\n constructor(\n private readonly routePaths: Map<RouteRef, string>,\n private readonly routeParents: Map<RouteRef, RouteRef | undefined>,\n private readonly routeObjects: BackstageRouteObject[],\n private readonly routeBindings: Map<\n ExternalRouteRef,\n RouteRef | SubRouteRef\n >,\n private readonly appBasePath: string, // base path without a trailing slash\n ) {}\n\n resolve<Params extends AnyParams>(\n anyRouteRef:\n | RouteRef<Params>\n | SubRouteRef<Params>\n | ExternalRouteRef<Params, any>,\n sourceLocation: Parameters<typeof matchRoutes>[1],\n ): RouteFunc<Params> | undefined {\n // First figure out what our target absolute ref is, as well as our target path.\n const [targetRef, targetPath] = resolveTargetRef(\n anyRouteRef,\n this.routePaths,\n this.routeBindings,\n );\n if (!targetRef) {\n return undefined;\n }\n\n // The location that we get passed in uses the full path, so start by trimming off\n // the app base path prefix in case we're running the app on a sub-path.\n let relativeSourceLocation: Parameters<typeof matchRoutes>[1];\n if (typeof sourceLocation === 'string') {\n relativeSourceLocation = this.trimPath(sourceLocation);\n } else if (sourceLocation.pathname) {\n relativeSourceLocation = {\n ...sourceLocation,\n pathname: this.trimPath(sourceLocation.pathname),\n };\n } else {\n relativeSourceLocation = sourceLocation;\n }\n\n // Next we figure out the base path, which is the combination of the common parent path\n // between our current location and our target location, as well as the additional path\n // that is the difference between the parent path and the base of our target location.\n const basePath =\n this.appBasePath +\n resolveBasePath(\n targetRef,\n relativeSourceLocation,\n this.routePaths,\n this.routeParents,\n this.routeObjects,\n );\n\n const routeFunc: RouteFunc<Params> = (...[params]) => {\n // We selectively encode some some known-dangerous characters in the\n // params. The reason that we don't perform a blanket `encodeURIComponent`\n // here is that this encoding was added defensively long after the initial\n // release of this code. There's likely to be many users of this code that\n // already encode their parameters knowing that this code didn't do this\n // for them in the past. Therefore, we are extra careful NOT to include\n // the percent character in this set, even though that might seem like a\n // bad idea.\n const encodedParams =\n params &&\n mapValues(params, value => {\n if (typeof value === 'string') {\n return value.replaceAll(/[&?#;\\/]/g, c => encodeURIComponent(c));\n }\n return value;\n });\n return joinPaths(basePath, generatePath(targetPath, encodedParams));\n };\n return routeFunc;\n }\n\n private trimPath(targetPath: string) {\n if (!targetPath) {\n return targetPath;\n }\n\n if (targetPath.startsWith(this.appBasePath)) {\n return targetPath.slice(this.appBasePath.length);\n }\n return targetPath;\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 { ReactNode } from 'react';\nimport {\n ExternalRouteRef,\n RouteRef,\n SubRouteRef,\n} from '@backstage/core-plugin-api';\nimport {\n createVersionedValueMap,\n createVersionedContext,\n} from '@backstage/version-bridge';\nimport { RouteResolver } from './RouteResolver';\nimport { BackstageRouteObject } from './types';\n\nconst RoutingContext = createVersionedContext<{ 1: RouteResolver }>(\n 'routing-context',\n);\n\ntype ProviderProps = {\n routePaths: Map<RouteRef, string>;\n routeParents: Map<RouteRef, RouteRef | undefined>;\n routeObjects: BackstageRouteObject[];\n routeBindings: Map<ExternalRouteRef, RouteRef | SubRouteRef>;\n basePath?: string;\n children: ReactNode;\n};\n\nexport const RoutingProvider = ({\n routePaths,\n routeParents,\n routeObjects,\n routeBindings,\n basePath = '',\n children,\n}: ProviderProps) => {\n const resolver = new RouteResolver(\n routePaths,\n routeParents,\n routeObjects,\n routeBindings,\n basePath,\n );\n\n const versionedValue = createVersionedValueMap({ 1: resolver });\n return (\n <RoutingContext.Provider value={versionedValue}>\n {children}\n </RoutingContext.Provider>\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 { PropsWithChildren } from 'react';\nimport {\n createVersionedValueMap,\n createVersionedContext,\n} from '@backstage/version-bridge';\nimport { AppContext as AppContextV1 } from './types';\n\nconst AppContext = createVersionedContext<{ 1: AppContextV1 }>('app-context');\n\ntype Props = {\n appContext: AppContextV1;\n};\n\nexport const AppContextProvider = ({\n appContext,\n children,\n}: PropsWithChildren<Props>) => {\n const versionedValue = createVersionedValueMap({ 1: appContext });\n\n return <AppContext.Provider value={versionedValue} children={children} />;\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 IdentityApi,\n ProfileInfo,\n BackstageUserIdentity,\n ErrorApi,\n DiscoveryApi,\n FetchApi,\n} from '@backstage/core-plugin-api';\nimport { startCookieAuthRefresh } from './startCookieAuthRefresh';\n\nfunction mkError(thing: string) {\n return new Error(\n `Tried to access IdentityApi ${thing} before app was loaded`,\n );\n}\n\nfunction logDeprecation(thing: string) {\n // eslint-disable-next-line no-console\n console.warn(\n `WARNING: Call to ${thing} is deprecated and will break in the future`,\n );\n}\n\n// We use this for a period of backwards compatibility. It is a hidden\n// compatibility that will allow old plugins to continue working for a limited time.\ntype CompatibilityIdentityApi = IdentityApi & {\n getUserId?(): string;\n getIdToken?(): Promise<string | undefined>;\n getProfile?(): ProfileInfo;\n};\n\n/**\n * Implementation of the connection between the App-wide IdentityApi\n * and sign-in page.\n */\nexport class AppIdentityProxy implements IdentityApi {\n private target?: CompatibilityIdentityApi;\n private waitForTarget: Promise<CompatibilityIdentityApi>;\n private resolveTarget: (api: CompatibilityIdentityApi) => void = () => {};\n private signOutTargetUrl = '/';\n\n #cookieAuthSignOut?: () => Promise<void>;\n\n constructor() {\n this.waitForTarget = new Promise<CompatibilityIdentityApi>(resolve => {\n this.resolveTarget = resolve;\n });\n }\n\n // This is called by the app manager once the sign-in page provides us with an implementation\n setTarget(\n identityApi: CompatibilityIdentityApi,\n targetOptions: { signOutTargetUrl: string },\n ) {\n this.target = identityApi;\n this.signOutTargetUrl = targetOptions.signOutTargetUrl;\n this.resolveTarget(identityApi);\n }\n\n getUserId(): string {\n if (!this.target) {\n throw mkError('getUserId');\n }\n if (!this.target.getUserId) {\n throw new Error('IdentityApi does not implement getUserId');\n }\n logDeprecation('getUserId');\n return this.target.getUserId();\n }\n\n getProfile(): ProfileInfo {\n if (!this.target) {\n throw mkError('getProfile');\n }\n if (!this.target.getProfile) {\n throw new Error('IdentityApi does not implement getProfile');\n }\n logDeprecation('getProfile');\n return this.target.getProfile();\n }\n\n async getProfileInfo(): Promise<ProfileInfo> {\n return this.waitForTarget.then(target => target.getProfileInfo());\n }\n\n async getBackstageIdentity(): Promise<BackstageUserIdentity> {\n const identity = await this.waitForTarget.then(target =>\n target.getBackstageIdentity(),\n );\n if (!identity.userEntityRef.match(/^.*:.*\\/.*$/)) {\n // eslint-disable-next-line no-console\n console.warn(\n `WARNING: The App IdentityApi provided an invalid userEntityRef, '${identity.userEntityRef}'. ` +\n `It must be a full Entity Reference of the form '<kind>:<namespace>/<name>'.`,\n );\n }\n\n return identity;\n }\n\n async getCredentials(): Promise<{ token?: string | undefined }> {\n return this.waitForTarget.then(target => target.getCredentials());\n }\n\n async getIdToken(): Promise<string | undefined> {\n return this.waitForTarget.then(target => {\n if (!target.getIdToken) {\n throw new Error('IdentityApi does not implement getIdToken');\n }\n logDeprecation('getIdToken');\n return target.getIdToken();\n });\n }\n\n async signOut(): Promise<void> {\n await this.waitForTarget.then(target => target.signOut());\n\n await this.#cookieAuthSignOut?.();\n\n window.location.href = this.signOutTargetUrl;\n }\n\n enableCookieAuth(ctx: {\n errorApi: ErrorApi;\n fetchApi: FetchApi;\n discoveryApi: DiscoveryApi;\n }) {\n if (this.#cookieAuthSignOut) {\n return;\n }\n\n const stopRefresh = startCookieAuthRefresh(ctx);\n\n this.#cookieAuthSignOut = async () => {\n stopRefresh();\n\n // It is fine if we do NOT worry yet about deleting cookies for OTHER backends like techdocs\n const appBaseUrl = await ctx.discoveryApi.getBaseUrl('app');\n try {\n await fetch(`${appBaseUrl}/.backstage/auth/v1/cookie`, {\n method: 'DELETE',\n credentials: 'include',\n });\n } catch {\n // Ignore the error for those who use static serving of the frontend\n }\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 { DiscoveryApi, ErrorApi, FetchApi } from '@backstage/core-plugin-api';\n\nconst PLUGIN_ID = 'app';\nconst CHANNEL_ID = `${PLUGIN_ID}-auth-cookie-expires-at`;\n\nconst MIN_BASE_DELAY_MS = 5 * 60_000;\n\nconst ERROR_BACKOFF_START = 5_000;\nconst ERROR_BACKOFF_FACTOR = 2;\nconst ERROR_BACKOFF_MAX = 5 * 60_000;\n\n// Messaging implementation and IDs must match\n// plugins/auth-react/src/hooks/useCookieAuthRefresh/useCookieAuthRefresh.tsx\nexport function startCookieAuthRefresh({\n discoveryApi,\n fetchApi,\n errorApi,\n}: {\n discoveryApi: DiscoveryApi;\n fetchApi: FetchApi;\n errorApi: ErrorApi;\n}) {\n let stopped = false;\n let timeout: NodeJS.Timeout | undefined;\n let firstError = true;\n let errorBackoff = ERROR_BACKOFF_START;\n\n const channel =\n 'BroadcastChannel' in window ? new BroadcastChannel(CHANNEL_ID) : undefined;\n\n // Randomize the refreshing margin with a margin of 1-4 minutes to avoid all tabs refreshing at the same time\n const getDelay = (expiresAt: number) => {\n const margin = (1 + 3 * Math.random()) * 60000;\n const delay = Math.max(expiresAt - Date.now(), MIN_BASE_DELAY_MS) - margin;\n return delay;\n };\n\n const refresh = async () => {\n try {\n const baseUrl = await discoveryApi.getBaseUrl(PLUGIN_ID);\n const requestUrl = `${baseUrl}/.backstage/auth/v1/cookie`;\n const res = await fetchApi.fetch(requestUrl, {\n credentials: 'include',\n });\n\n if (!res.ok) {\n throw new Error(\n `Request failed with status ${res.status} ${res.statusText}, see request towards ${requestUrl} for more details`,\n );\n }\n\n const data = await res.json();\n if (!data.expiresAt) {\n throw new Error('No expiration date in response');\n }\n\n const expiresAt = Date.parse(data.expiresAt);\n if (Number.isNaN(expiresAt)) {\n throw new Error('Invalid expiration date in response');\n }\n\n firstError = true;\n\n channel?.postMessage({\n action: 'COOKIE_REFRESH_SUCCESS',\n payload: { expiresAt: new Date(expiresAt).toISOString() },\n });\n\n scheduleRefresh(getDelay(expiresAt));\n } catch (error) {\n // Ignore the first error after successful requests\n if (firstError) {\n firstError = false;\n errorBackoff = ERROR_BACKOFF_START;\n } else {\n errorBackoff = Math.min(\n ERROR_BACKOFF_MAX,\n errorBackoff * ERROR_BACKOFF_FACTOR,\n );\n // eslint-disable-next-line no-console\n console.error('Session cookie refresh failed', error);\n errorApi.post(\n new Error(\n `Session refresh failed, see developer console for details`,\n ),\n );\n }\n\n scheduleRefresh(errorBackoff);\n }\n };\n\n const onMessage = (\n event: MessageEvent<\n | {\n action: 'COOKIE_REFRESH_SUCCESS';\n payload: { expiresAt: string };\n }\n | object\n >,\n ) => {\n const { data } = event;\n if (data === null || typeof data !== 'object') {\n return;\n }\n if ('action' in data && data.action === 'COOKIE_REFRESH_SUCCESS') {\n const expiresAt = Date.parse(data.payload.expiresAt);\n if (Number.isNaN(expiresAt)) {\n // eslint-disable-next-line no-console\n console.warn(\n 'Received invalid expiration from session refresh channel',\n );\n return;\n }\n\n scheduleRefresh(getDelay(expiresAt));\n }\n };\n\n function scheduleRefresh(delayMs: number) {\n if (stopped) {\n return;\n }\n if (timeout) {\n clearTimeout(timeout);\n }\n timeout = setTimeout(refresh, delayMs);\n }\n\n channel?.addEventListener('message', onMessage);\n refresh();\n\n return () => {\n stopped = true;\n if (timeout) {\n clearTimeout(timeout);\n }\n channel?.removeEventListener('message', onMessage);\n channel?.close();\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 { useMemo, useEffect, useState, PropsWithChildren } from 'react';\nimport { useApi, appThemeApiRef, AppTheme } from '@backstage/core-plugin-api';\nimport useObservable from 'react-use/esm/useObservable';\n\n// This tries to find the most accurate match, but also falls back to less\n// accurate results in order to avoid errors.\nfunction resolveTheme(\n themeId: string | undefined,\n shouldPreferDark: boolean,\n themes: AppTheme[],\n) {\n if (themeId !== undefined) {\n const selectedTheme = themes.find(theme => theme.id === themeId);\n if (selectedTheme) {\n return selectedTheme;\n }\n }\n\n if (shouldPreferDark) {\n const darkTheme = themes.find(theme => theme.variant === 'dark');\n if (darkTheme) {\n return darkTheme;\n }\n }\n\n const lightTheme = themes.find(theme => theme.variant === 'light');\n if (lightTheme) {\n return lightTheme;\n }\n\n return themes[0];\n}\n\nconst useShouldPreferDarkTheme = () => {\n const mediaQuery = useMemo(\n () => window.matchMedia('(prefers-color-scheme: dark)'),\n [],\n );\n const [shouldPreferDark, setPrefersDark] = useState(mediaQuery.matches);\n\n useEffect(() => {\n const listener = (event: MediaQueryListEvent) => {\n setPrefersDark(event.matches);\n };\n mediaQuery.addListener(listener);\n return () => {\n mediaQuery.removeListener(listener);\n };\n }, [mediaQuery]);\n\n return shouldPreferDark;\n};\n\nexport function AppThemeProvider({ children }: PropsWithChildren<{}>) {\n const appThemeApi = useApi(appThemeApiRef);\n const themeId = useObservable(\n appThemeApi.activeThemeId$(),\n appThemeApi.getActiveThemeId(),\n );\n\n // Browser feature detection won't change over time, so ignore lint rule\n const shouldPreferDark = Boolean(window.matchMedia)\n ? useShouldPreferDarkTheme() // eslint-disable-line react-hooks/rules-of-hooks\n : false;\n\n const appTheme = resolveTheme(\n themeId,\n shouldPreferDark,\n appThemeApi.getInstalledThemes(),\n );\n if (!appTheme) {\n throw new Error('App has no themes');\n }\n\n return <appTheme.Provider children={children} />;\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 { AppConfig } from '@backstage/config';\nimport { JsonObject } from '@backstage/types';\nimport { AppConfigLoader } from './types';\n\n/**\n * The default config loader, which expects that config is available at compile-time\n * in `process.env.APP_CONFIG`. APP_CONFIG should be an array of config objects as\n * returned by the config loader.\n *\n * It will also load runtime config from the __APP_INJECTED_RUNTIME_CONFIG__ string,\n * which can be rewritten at runtime to contain an additional JSON config object.\n * If runtime config is present, it will be placed first in the config array, overriding\n * other config values.\n *\n * @public\n */\nexport const defaultConfigLoader: AppConfigLoader = async () =>\n defaultConfigLoaderSync();\n\n/** @internal */\nexport function defaultConfigLoaderSync(\n // This string may be replaced at runtime to provide additional config.\n // It should be replaced by a JSON-serialized config object.\n // It's a param so we can test it, but at runtime this will always fall back to default.\n runtimeConfigJson: string = '__APP_INJECTED_RUNTIME_CONFIG__',\n) {\n const configs = new Array<AppConfig>();\n\n const staticConfig = process.env.APP_CONFIG;\n if (staticConfig) {\n if (!Array.isArray(staticConfig)) {\n throw new Error('Static configuration has invalid format');\n }\n configs.push(...staticConfig);\n }\n\n // Check if we have any config script tags, otherwise fall back to injected config\n const configScripts = document.querySelectorAll(\n 'script[type=\"backstage.io/config\"]',\n );\n if (configScripts.length > 0) {\n for (const el of configScripts) {\n try {\n const content = el.textContent;\n if (!content) {\n throw new Error('tag is empty');\n }\n let data;\n try {\n data = JSON.parse(content);\n } catch (error) {\n throw new Error(`failed to parse config; ${error}`);\n }\n if (!Array.isArray(data)) {\n throw new Error('data is not an array');\n }\n configs.push(...data);\n } catch (error) {\n throw new Error(\n `Failed to load config from script tag, ${error.message}`,\n );\n }\n }\n } else if (\n runtimeConfigJson !==\n // Avoiding this string also being replaced at runtime\n '__app_injected_runtime_config__'.toLocaleUpperCase('en-US')\n ) {\n try {\n const data = JSON.parse(runtimeConfigJson) as JsonObject;\n if (Array.isArray(data)) {\n configs.push(...data);\n } else {\n configs.push({ data, context: 'env' });\n }\n } catch (error) {\n throw new Error(`Failed to load runtime configuration, ${error}`);\n }\n }\n\n const windowAppConfig = (window as any).__APP_CONFIG__;\n if (windowAppConfig) {\n configs.push({\n context: 'window',\n data: windowAppConfig,\n });\n }\n return configs;\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 { ApiRef, ApiHolder } from '@backstage/core-plugin-api';\n\ntype ApiImpl<T = unknown> = readonly [ApiRef<T>, T];\n\n/** @internal */\nclass ApiRegistryBuilder {\n private apis: [string, unknown][] = [];\n\n add<T, I extends T>(api: ApiRef<T>, impl: I): I {\n this.apis.push([api.id, impl]);\n return impl;\n }\n\n build(): ApiRegistry {\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n return new ApiRegistry(new Map(this.apis));\n }\n}\n\n/**\n * A registry for utility APIs.\n *\n * @internal\n */\nexport class ApiRegistry implements ApiHolder {\n static builder() {\n return new ApiRegistryBuilder();\n }\n\n /**\n * Creates a new ApiRegistry with a list of API implementations.\n *\n * @param apis - A list of pairs mapping an ApiRef to its respective implementation\n */\n static from(apis: ApiImpl[]) {\n return new ApiRegistry(new Map(apis.map(([api, impl]) => [api.id, impl])));\n }\n\n /**\n * Creates a new ApiRegistry with a single API implementation.\n *\n * @param api - ApiRef for the API to add\n * @param impl - Implementation of the API to add\n */\n static with<T>(api: ApiRef<T>, impl: T): ApiRegistry {\n return new ApiRegistry(new Map([[api.id, impl]]));\n }\n\n constructor(private readonly apis: Map<string, unknown>) {}\n\n /**\n * Returns a new ApiRegistry with the provided API added to the existing ones.\n *\n * @param api - ApiRef for the API to add\n * @param impl - Implementation of the API to add\n */\n with<T>(api: ApiRef<T>, impl: T): ApiRegistry {\n return new ApiRegistry(new Map([...this.apis, [api.id, impl]]));\n }\n\n get<T>(api: ApiRef<T>): T | undefined {\n return this.apis.get(api.id) as T | undefined;\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 */\n\nimport { createRoutesFromChildren, Route } from 'react-router-dom';\n\nexport function isReactRouterBeta(): boolean {\n const [obj] = createRoutesFromChildren(<Route index element={<div />} />);\n return !obj.index;\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 */\n\nimport { createContext } from 'react';\nimport { AppIdentityProxy } from '../apis/implementations/IdentityApi/AppIdentityProxy';\nimport { BackstageRouteObject } from '../routing/types';\n\nexport const InternalAppContext = createContext<\n | undefined\n | {\n routeObjects: BackstageRouteObject[];\n appIdentityProxy: AppIdentityProxy;\n }\n>(undefined);\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 { matchRoutes, useLocation } from 'react-router-dom';\nimport {\n useAnalytics,\n AnalyticsContext,\n RouteRef,\n AnalyticsEventAttributes,\n BackstagePlugin,\n} from '@backstage/core-plugin-api';\nimport { BackstageRouteObject } from './types';\n\n/**\n * Returns an extension context given the current pathname and a list of\n * Backstage route objects.\n */\nconst getExtensionContext = (\n pathname: string,\n routes: BackstageRouteObject[],\n) => {\n try {\n // Find matching routes for the given path name.\n const matches = matchRoutes(routes, { pathname });\n\n // Of the matching routes, get the last (e.g. most specific) instance of\n // the BackstageRouteObject that contains a routeRef. Filtering by routeRef\n // ensures subRouteRefs are aligned to their parent routes' context.\n const routeMatch = matches\n ?.filter(match => match?.route.routeRefs?.size > 0)\n .pop();\n const routeObject = routeMatch?.route;\n\n // If there is no route object, then allow inheritance of default context.\n if (!routeObject) {\n return undefined;\n }\n\n // If the matched route is the root route (no path), and the pathname is\n // not the path of the homepage, then inherit from the default context.\n if (routeObject.path === '' && pathname !== '/') {\n return undefined;\n }\n\n // If there is a single route ref, use it.\n let routeRef: RouteRef | undefined;\n if (routeObject.routeRefs.size === 1) {\n routeRef = routeObject.routeRefs.values().next().value;\n }\n\n // If there is a single plugin, use it.\n let plugin: BackstagePlugin | undefined;\n if (routeObject.plugins.size === 1) {\n plugin = routeObject.plugins.values().next().value;\n }\n\n const params = Object.entries(\n routeMatch?.params || {},\n ).reduce<AnalyticsEventAttributes>((acc, [key, value]) => {\n if (value !== undefined && key !== '*') {\n acc[key] = value;\n }\n return acc;\n }, {});\n\n return {\n extension: 'App',\n pluginId: plugin?.getId() || 'root',\n ...(routeRef ? { routeRef: (routeRef as { id?: string }).id } : {}),\n _routeNodeType: routeObject.element as string,\n params,\n };\n } catch {\n return undefined;\n }\n};\n\n/**\n * Performs the actual event capture on render.\n */\nconst TrackNavigation = ({\n pathname,\n search,\n hash,\n attributes,\n}: {\n pathname: string;\n search: string;\n hash: string;\n attributes?: AnalyticsEventAttributes;\n}) => {\n const analytics = useAnalytics();\n useEffect(() => {\n analytics.captureEvent('navigate', `${pathname}${search}${hash}`, {\n attributes,\n });\n }, [analytics, pathname, search, hash, attributes]);\n\n return null;\n};\n\n/**\n * Logs a \"navigate\" event with appropriate plugin-level analytics context\n * attributes each time the user navigates to a page.\n */\nexport const RouteTracker = ({\n routeObjects,\n}: {\n routeObjects: BackstageRouteObject[];\n}) => {\n const { pathname, search, hash } = useLocation();\n\n const { params, ...attributes } = getExtensionContext(\n pathname,\n routeObjects,\n ) || { params: {} };\n\n return (\n <AnalyticsContext attributes={attributes}>\n <TrackNavigation\n pathname={pathname}\n search={search}\n hash={hash}\n attributes={params}\n />\n </AnalyticsContext>\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 */\n\nimport { useContext, ReactNode, ComponentType, useState } from 'react';\nimport {\n attachComponentData,\n ConfigApi,\n configApiRef,\n IdentityApi,\n SignInPageProps,\n useApi,\n useApp,\n} from '@backstage/core-plugin-api';\nimport { InternalAppContext } from './InternalAppContext';\nimport { isReactRouterBeta } from './isReactRouterBeta';\nimport { RouteTracker } from '../routing/RouteTracker';\nimport { Route, Routes } from 'react-router-dom';\nimport { AppIdentityProxy } from '../apis/implementations/IdentityApi/AppIdentityProxy';\n\n/**\n * Get the app base path from the configured app baseUrl.\n *\n * The returned path does not have a trailing slash.\n */\nexport function getBasePath(configApi: ConfigApi) {\n if (!isReactRouterBeta()) {\n // When using rr v6 stable the base path is handled through the\n // basename prop on the router component instead.\n return '';\n }\n\n return readBasePath(configApi);\n}\n\n/**\n * Read the configured base path.\n *\n * The returned path does not have a trailing slash.\n */\nfunction readBasePath(configApi: ConfigApi) {\n let { pathname } = new URL(\n configApi.getOptionalString('app.baseUrl') ?? '/',\n 'http://sample.dev', // baseUrl can be specified as just a path\n );\n pathname = pathname.replace(/\\/*$/, '');\n return pathname;\n}\n\n// This wraps the sign-in page and waits for sign-in to be completed before rendering the app\nfunction SignInPageWrapper({\n component: Component,\n appIdentityProxy,\n children,\n}: {\n component: ComponentType<SignInPageProps>;\n appIdentityProxy: AppIdentityProxy;\n children: ReactNode;\n}) {\n const [identityApi, setIdentityApi] = useState<IdentityApi>();\n const configApi = useApi(configApiRef);\n const basePath = readBasePath(configApi);\n\n if (!identityApi) {\n return <Component onSignInSuccess={setIdentityApi} />;\n }\n\n appIdentityProxy.setTarget(identityApi, {\n signOutTargetUrl: basePath || '/',\n });\n return <>{children}</>;\n}\n\n/**\n * Props for the {@link AppRouter} component.\n * @public\n */\nexport interface AppRouterProps {\n children?: ReactNode;\n}\n\n/**\n * App router and sign-in page wrapper.\n *\n * @public\n * @remarks\n *\n * The AppRouter provides the routing context and renders the sign-in page.\n * Until the user has successfully signed in, this component will render\n * the sign-in page. Once the user has signed-in, it will instead render\n * the app, while providing routing and route tracking for the app.\n */\nexport function AppRouter(props: AppRouterProps) {\n const { Router: RouterComponent, SignInPage: SignInPageComponent } =\n useApp().getComponents();\n\n const configApi = useApi(configApiRef);\n const basePath = readBasePath(configApi);\n const mountPath = `${basePath}/*`;\n const internalAppContext = useContext(InternalAppContext);\n if (!internalAppContext) {\n throw new Error('AppRouter must be rendered within the AppProvider');\n }\n const { routeObjects, appIdentityProxy } = internalAppContext;\n\n // If the app hasn't configured a sign-in page, we just continue as guest.\n if (!SignInPageComponent) {\n appIdentityProxy.setTarget(\n {\n getUserId: () => 'guest',\n getIdToken: async () => undefined,\n getProfile: () => ({\n email: 'guest@example.com',\n displayName: 'Guest',\n }),\n getProfileInfo: async () => ({\n email: 'guest@example.com',\n displayName: 'Guest',\n }),\n getBackstageIdentity: async () => ({\n type: 'user',\n userEntityRef: 'user:default/guest',\n ownershipEntityRefs: ['user:default/guest'],\n }),\n getCredentials: async () => ({}),\n signOut: async () => {},\n },\n { signOutTargetUrl: basePath || '/' },\n );\n\n if (isReactRouterBeta()) {\n return (\n <RouterComponent>\n <RouteTracker routeObjects={routeObjects} />\n <Routes>\n <Route path={mountPath} element={<>{props.children}</>} />\n </Routes>\n </RouterComponent>\n );\n }\n\n return (\n <RouterComponent basename={basePath}>\n <RouteTracker routeObjects={routeObjects} />\n {props.children}\n </RouterComponent>\n );\n }\n\n if (isReactRouterBeta()) {\n return (\n <RouterComponent>\n <RouteTracker routeObjects={routeObjects} />\n <SignInPageWrapper\n component={SignInPageComponent}\n appIdentityProxy={appIdentityProxy}\n >\n <Routes>\n <Route path={mountPath} element={<>{props.children}</>} />\n </Routes>\n </SignInPageWrapper>\n </RouterComponent>\n );\n }\n\n return (\n <RouterComponent basename={basePath}>\n <RouteTracker routeObjects={routeObjects} />\n <SignInPageWrapper\n component={SignInPageComponent}\n appIdentityProxy={appIdentityProxy}\n >\n {props.children}\n </SignInPageWrapper>\n </RouterComponent>\n );\n}\n\nattachComponentData(AppRouter, 'core.type', 'AppRouter');\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\n// Internal import to avoid code duplication, this will lead to duplication in build output\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { AppLanguageApi } from '@backstage/core-plugin-api/alpha';\nimport { Observable } from '@backstage/types';\nimport { BehaviorSubject } from '../../../lib';\n\nconst STORAGE_KEY = 'language';\nexport const DEFAULT_LANGUAGE = 'en';\n\n/** @alpha */\nexport interface AppLanguageSelectorOptions {\n defaultLanguage?: string;\n availableLanguages?: string[];\n}\n\n/**\n * Exposes the available languages in the app and allows for switching of the active language.\n *\n * @alpha\n */\nexport class AppLanguageSelector implements AppLanguageApi {\n static create(options?: AppLanguageSelectorOptions) {\n const languages = options?.availableLanguages ?? [DEFAULT_LANGUAGE];\n if (languages.length !== new Set(languages).size) {\n throw new Error(\n `Supported languages may not contain duplicates, got '${languages.join(\n \"', '\",\n )}'`,\n );\n }\n if (!languages.includes(DEFAULT_LANGUAGE)) {\n throw new Error(`Supported languages must include '${DEFAULT_LANGUAGE}'`);\n }\n\n const initialLanguage = options?.defaultLanguage ?? DEFAULT_LANGUAGE;\n if (!languages.includes(initialLanguage)) {\n throw new Error(\n `Initial language must be one of the supported languages, got '${initialLanguage}'`,\n );\n }\n\n return new AppLanguageSelector(languages, initialLanguage);\n }\n\n static createWithStorage(options?: AppLanguageSelectorOptions) {\n const selector = AppLanguageSelector.create(options);\n\n if (!window.localStorage) {\n return selector;\n }\n\n const storedLanguage = window.localStorage.getItem(STORAGE_KEY);\n const { languages } = selector.getAvailableLanguages();\n if (storedLanguage && languages.includes(storedLanguage)) {\n selector.setLanguage(storedLanguage);\n }\n\n selector.language$().subscribe(({ language }) => {\n if (language !== window.localStorage.getItem(STORAGE_KEY)) {\n window.localStorage.setItem(STORAGE_KEY, language);\n }\n });\n\n window.addEventListener('storage', event => {\n if (event.key === STORAGE_KEY) {\n const language = localStorage.getItem(STORAGE_KEY) ?? undefined;\n if (language) {\n selector.setLanguage(language);\n }\n }\n });\n\n return selector;\n }\n\n #languages: string[];\n #language: string;\n #subject: BehaviorSubject<{ language: string }>;\n\n private constructor(languages: string[], initialLanguage: string) {\n this.#languages = languages;\n this.#language = initialLanguage;\n this.#subject = new BehaviorSubject<{ language: string }>({\n language: this.#language,\n });\n }\n\n getAvailableLanguages(): { languages: string[] } {\n return { languages: this.#languages.slice() };\n }\n\n setLanguage(language?: string | undefined): void {\n const lng = language ?? DEFAULT_LANGUAGE;\n if (lng === this.#language) {\n return;\n }\n if (lng && !this.#languages.includes(lng)) {\n throw new Error(\n `Failed to change language to '${lng}', available languages are '${this.#languages.join(\n \"', '\",\n )}'`,\n );\n }\n this.#language = lng;\n this.#subject.next({ language: lng });\n }\n\n getLanguage(): { language: string } {\n return { language: this.#language };\n }\n\n language$(): Observable<{ language: string }> {\n return this.#subject;\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 {\n AppLanguageApi,\n TranslationApi,\n TranslationFunction,\n TranslationMessages,\n TranslationRef,\n TranslationResource,\n TranslationSnapshot,\n} from '@backstage/core-plugin-api/alpha';\nimport {\n createInstance as createI18n,\n FormatFunction,\n Interpolator,\n TFunction,\n type i18n as I18n,\n} from 'i18next';\nimport ObservableImpl from 'zen-observable';\n\n// Internal import to avoid code duplication, this will lead to duplication in build output\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport {\n toInternalTranslationResource,\n InternalTranslationResourceLoader,\n} from '../../../../../core-plugin-api/src/translation/TranslationResource';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport {\n toInternalTranslationRef,\n InternalTranslationRef,\n} from '../../../../../core-plugin-api/src/translation/TranslationRef';\nimport { Observable } from '@backstage/types';\nimport { DEFAULT_LANGUAGE } from '../AppLanguageApi/AppLanguageSelector';\nimport { createElement, Fragment, ReactNode, isValidElement } from 'react';\n\n/** @alpha */\nexport interface I18nextTranslationApiOptions {\n languageApi: AppLanguageApi;\n resources?: Array<TranslationMessages | TranslationResource>;\n}\n\nfunction removeNulls(\n messages: Record<string, string | null>,\n): Record<string, string> {\n return Object.fromEntries(\n Object.entries(messages).filter(\n (e): e is [string, string] => e[1] !== null,\n ),\n );\n}\n\n/**\n * The built-in i18next backend loading logic doesn't handle on the fly switches\n * of language very well. It gets a bit confused about whether resources are actually\n * loaded or not, so instead we implement our own resource loader.\n */\nclass ResourceLoader {\n /** Loaded resources by loader key */\n #loaded = new Set<string>();\n /** Resource loading promises by loader key */\n #loading = new Map<string, Promise<void>>();\n /** Loaders for each resource language */\n #loaders = new Map<string, InternalTranslationResourceLoader>();\n\n constructor(\n private readonly onLoad: (loaded: {\n language: string;\n namespace: string;\n messages: Record<string, string | null>;\n }) => void,\n ) {}\n\n addTranslationResource(resource: TranslationResource) {\n const internalResource = toInternalTranslationResource(resource);\n for (const entry of internalResource.resources) {\n const key = this.#getLoaderKey(entry.language, internalResource.id);\n\n // First loader to register wins, this means that resources registered in the app\n // have priority over default resource from translation refs\n if (!this.#loaders.has(key)) {\n this.#loaders.set(key, entry.loader);\n }\n }\n }\n\n #getLoaderKey(language: string, namespace: string) {\n return `${language}/${namespace}`;\n }\n\n needsLoading(language: string, namespace: string) {\n const key = this.#getLoaderKey(language, namespace);\n const loader = this.#loaders.get(key);\n if (!loader) {\n return false;\n }\n\n return !this.#loaded.has(key);\n }\n\n async load(language: string, namespace: string): Promise<void> {\n const key = this.#getLoaderKey(language, namespace);\n\n const loader = this.#loaders.get(key);\n if (!loader) {\n return;\n }\n\n if (this.#loaded.has(key)) {\n return;\n }\n\n const loading = this.#loading.get(key);\n if (loading) {\n await loading;\n return;\n }\n\n const load = loader().then(\n result => {\n this.onLoad({ language, namespace, messages: result.messages });\n this.#loaded.add(key);\n },\n error => {\n this.#loaded.add(key); // Do not try to load failed resources again\n throw error;\n },\n );\n this.#loading.set(key, load);\n await load;\n }\n}\n\n/**\n * A helper for implementing JSX interpolation\n */\nexport class JsxInterpolator {\n readonly #setFormatHook: (hook: FormatFunction) => void;\n readonly #marker: string;\n readonly #pattern: RegExp;\n\n static fromI18n(i18n: I18n) {\n const interpolator = i18n.services.interpolator as Interpolator & {\n format: FormatFunction;\n };\n const originalFormat = interpolator.format;\n\n let formatHook: FormatFunction | undefined;\n\n // This is the only way to override the format function of the interpolator\n // without overriding the default formatters. See the behavior here:\n // https://github.com/i18next/i18next/blob/c633121e57e2b6024080142d78027842bf2a6e5e/src/i18next.js#L120-L125\n interpolator.format = (value, format, lng, formatOpts) => {\n if (format) {\n return originalFormat(value, format, lng, formatOpts);\n }\n return formatHook?.(value, format, lng, formatOpts) ?? value;\n };\n\n return new JsxInterpolator(\n // Using a random marker to ensure it can't be misused\n Math.random().toString(36).substring(2, 8),\n hook => {\n formatHook = hook;\n },\n );\n }\n\n private constructor(\n marker: string,\n setFormatHook: (hook: FormatFunction) => void,\n ) {\n this.#setFormatHook = setFormatHook;\n this.#marker = marker;\n this.#pattern = new RegExp(`\\\\$${marker}\\\\(([^)]+)\\\\)`);\n }\n\n wrapT<TMessages extends { [key in string]: string }>(\n originalT: TFunction,\n ): TranslationFunction<TMessages> {\n return ((key, options) => {\n let elementsMap: Map<string, ReactNode> | undefined = undefined;\n\n // There's no way to override the format hook via the translation function\n // options, event though types indicate that it might be possible.\n // Instead, override the format function hook before every invocation and\n // rely on synchronous execution.\n this.#setFormatHook(value => {\n if (isValidElement(value)) {\n if (!elementsMap) {\n elementsMap = new Map();\n }\n const elementKey = elementsMap.size.toString();\n elementsMap.set(elementKey, value);\n\n return `$${this.#marker}(${elementKey})`;\n }\n return value;\n });\n\n // Overriding the return options is not allowed via TranslationFunction,\n // so this will always be a string\n const result = originalT(key, options as any) as unknown as string;\n if (!elementsMap) {\n return result;\n }\n\n const split = result.split(this.#pattern);\n\n return createElement(\n Fragment,\n null,\n ...split\n .map((part, index) => {\n if (index % 2 === 0) {\n return part;\n }\n return elementsMap?.get(part);\n })\n .filter(Boolean),\n );\n }) as TranslationFunction<TMessages>;\n }\n}\n\n/** @alpha */\nexport class I18nextTranslationApi implements TranslationApi {\n static create(options: I18nextTranslationApiOptions) {\n const { languages } = options.languageApi.getAvailableLanguages();\n\n const i18n = createI18n({\n fallbackLng: DEFAULT_LANGUAGE,\n supportedLngs: languages,\n interpolation: {\n escapeValue: false,\n // Used for the JsxInterpolator format hook\n alwaysFormat: true,\n },\n ns: [],\n defaultNS: false,\n fallbackNS: false,\n\n // Disable resource loading on init, meaning i18n will be ready to use immediately\n initImmediate: false,\n });\n\n i18n.init();\n if (!i18n.isInitialized) {\n throw new Error('i18next was unexpectedly not initialized');\n }\n\n const interpolator = JsxInterpolator.fromI18n(i18n);\n\n const { language: initialLanguage } = options.languageApi.getLanguage();\n if (initialLanguage !== DEFAULT_LANGUAGE) {\n i18n.changeLanguage(initialLanguage);\n }\n\n const loader = new ResourceLoader(loaded => {\n i18n.addResourceBundle(\n loaded.language,\n loaded.namespace,\n removeNulls(loaded.messages),\n false, // do not merge with existing translations\n true, // overwrite translations\n );\n });\n\n const resources = options?.resources || [];\n // Iterate in reverse, giving higher priority to resources registered later\n for (let i = resources.length - 1; i >= 0; i--) {\n const resource = resources[i];\n if (resource.$$type === '@backstage/TranslationResource') {\n loader.addTranslationResource(resource);\n } else if (resource.$$type === '@backstage/TranslationMessages') {\n // Overrides for default messages, created with createTranslationMessages and installed via app\n i18n.addResourceBundle(\n DEFAULT_LANGUAGE,\n resource.id,\n removeNulls(resource.messages),\n true, // merge with existing translations\n false, // do not overwrite translations\n );\n }\n }\n\n const instance = new I18nextTranslationApi(\n i18n,\n loader,\n options.languageApi.getLanguage().language,\n interpolator,\n );\n\n options.languageApi.language$().subscribe(({ language }) => {\n instance.#changeLanguage(language);\n });\n\n return instance;\n }\n\n #i18n: I18n;\n #loader: ResourceLoader;\n #language: string;\n #jsxInterpolator: JsxInterpolator;\n\n /** Keep track of which refs we have registered default resources for */\n #registeredRefs = new Set<string>();\n /** Notify observers when language changes */\n #languageChangeListeners = new Set<() => void>();\n\n private constructor(\n i18n: I18n,\n loader: ResourceLoader,\n language: string,\n jsxInterpolator: JsxInterpolator,\n ) {\n this.#i18n = i18n;\n this.#loader = loader;\n this.#language = language;\n this.#jsxInterpolator = jsxInterpolator;\n }\n\n getTranslation<TMessages extends { [key in string]: string }>(\n translationRef: TranslationRef<string, TMessages>,\n ): TranslationSnapshot<TMessages> {\n const internalRef = toInternalTranslationRef(translationRef);\n\n this.#registerDefaults(internalRef);\n\n return this.#createSnapshot(internalRef);\n }\n\n translation$<TMessages extends { [key in string]: string }>(\n translationRef: TranslationRef<string, TMessages>,\n ): Observable<TranslationSnapshot<TMessages>> {\n const internalRef = toInternalTranslationRef(translationRef);\n\n this.#registerDefaults(internalRef);\n\n return new ObservableImpl<TranslationSnapshot<TMessages>>(subscriber => {\n let loadTicket = {}; // To check for stale loads\n\n const loadResource = () => {\n loadTicket = {};\n const ticket = loadTicket;\n this.#loader.load(this.#language, internalRef.id).then(\n () => {\n if (ticket === loadTicket) {\n const snapshot = this.#createSnapshot(internalRef);\n if (snapshot.ready) {\n subscriber.next(snapshot);\n }\n }\n },\n error => {\n if (ticket === loadTicket) {\n subscriber.error(Array.isArray(error) ? error[0] : error);\n }\n },\n );\n };\n\n const onChange = () => {\n const snapshot = this.#createSnapshot(internalRef);\n if (snapshot.ready) {\n subscriber.next(snapshot);\n } else {\n loadResource();\n }\n };\n\n if (this.#loader.needsLoading(this.#language, internalRef.id)) {\n loadResource();\n }\n\n this.#languageChangeListeners.add(onChange);\n return () => {\n this.#languageChangeListeners.delete(onChange);\n };\n });\n }\n\n #changeLanguage(language: string): void {\n if (this.#language !== language) {\n this.#language = language;\n this.#i18n.changeLanguage(language);\n this.#languageChangeListeners.forEach(listener => listener());\n }\n }\n\n #createSnapshot<TMessages extends { [key in string]: string }>(\n internalRef: InternalTranslationRef<string, TMessages>,\n ): TranslationSnapshot<TMessages> {\n if (this.#loader.needsLoading(this.#language, internalRef.id)) {\n return { ready: false };\n }\n\n const unwrappedT = this.#i18n.getFixedT(null, internalRef.id);\n const t = this.#jsxInterpolator.wrapT<TMessages>(unwrappedT);\n\n return {\n ready: true,\n t,\n };\n }\n\n #registerDefaults(internalRef: InternalTranslationRef): void {\n if (this.#registeredRefs.has(internalRef.id)) {\n return;\n }\n this.#registeredRefs.add(internalRef.id);\n\n const defaultMessages = internalRef.getDefaultMessages();\n this.#i18n.addResourceBundle(\n DEFAULT_LANGUAGE,\n internalRef.id,\n defaultMessages,\n true, // merge with existing translations\n false, // do not overwrite translations\n );\n\n const defaultResource = internalRef.getDefaultResource();\n if (defaultResource) {\n this.#loader.addTranslationResource(defaultResource);\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 */\n\nimport { AppConfig, ConfigReader } from '@backstage/config';\n\n/**\n * Creates a base URL that uses to the current document origin.\n */\nfunction createLocalBaseUrl(fullUrl: string): string {\n const url = new URL(fullUrl);\n url.protocol = document.location.protocol;\n url.hostname = document.location.hostname;\n url.port = document.location.port;\n return url.toString().replace(/\\/$/, '');\n}\n\n/**\n * If we are able to override the app and backend base URLs to values that\n * match the origin of the current location, then this function returns a\n * new array of app configs that contain the overrides.\n *\n * @internal\n */\nexport function overrideBaseUrlConfigs(inputConfigs: AppConfig[]): AppConfig[] {\n const urlConfigReader = ConfigReader.fromConfigs(inputConfigs);\n\n // In tests we may not have `app.baseUrl` or `backend.baseUrl`, to keep them optional\n const appBaseUrl = urlConfigReader.getOptionalString('app.baseUrl');\n const backendBaseUrl = urlConfigReader.getOptionalString('backend.baseUrl');\n\n let configs = inputConfigs;\n\n let newBackendBaseUrl: string | undefined = undefined;\n let newAppBaseUrl: string | undefined = undefined;\n\n if (appBaseUrl && backendBaseUrl) {\n const appOrigin = new URL(appBaseUrl).origin;\n const backendOrigin = new URL(backendBaseUrl).origin;\n\n if (appOrigin === backendOrigin) {\n const maybeNewBackendBaseUrl = createLocalBaseUrl(backendBaseUrl);\n if (backendBaseUrl !== maybeNewBackendBaseUrl) {\n newBackendBaseUrl = maybeNewBackendBaseUrl;\n }\n }\n }\n\n if (appBaseUrl) {\n const maybeNewAppBaseUrl = createLocalBaseUrl(appBaseUrl);\n if (appBaseUrl !== maybeNewAppBaseUrl) {\n newAppBaseUrl = maybeNewAppBaseUrl;\n }\n }\n\n // Only add the relative config if there is actually data to add.\n if (newAppBaseUrl || newBackendBaseUrl) {\n configs = configs.concat({\n data: {\n app: newAppBaseUrl && {\n baseUrl: newAppBaseUrl,\n },\n backend: newBackendBaseUrl && {\n baseUrl: newBackendBaseUrl,\n },\n },\n context: 'relative-resolver',\n });\n }\n\n return configs;\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 { Config } from '@backstage/config';\nimport {\n ComponentType,\n PropsWithChildren,\n Suspense,\n useMemo,\n useRef,\n} from 'react';\nimport useAsync from 'react-use/esm/useAsync';\nimport {\n ApiProvider,\n AppThemeSelector,\n ConfigReader,\n LocalStorageFeatureFlags,\n} from '../apis';\nimport {\n AnyApiFactory,\n ApiHolder,\n IconComponent,\n AppTheme,\n appThemeApiRef,\n configApiRef,\n AppThemeApi,\n ConfigApi,\n featureFlagsApiRef,\n identityApiRef,\n BackstagePlugin,\n FeatureFlag,\n fetchApiRef,\n discoveryApiRef,\n errorApiRef,\n} from '@backstage/core-plugin-api';\nimport {\n AppLanguageApi,\n appLanguageApiRef,\n translationApiRef,\n TranslationMessages,\n TranslationResource,\n} from '@backstage/core-plugin-api/alpha';\nimport { ApiFactoryRegistry, ApiResolver } from '../apis/system';\nimport {\n childDiscoverer,\n routeElementDiscoverer,\n traverseElementTree,\n} from '../extensions/traversal';\nimport { pluginCollector } from '../plugins/collectors';\nimport {\n featureFlagCollector,\n routingV1Collector,\n routingV2Collector,\n} from '../routing/collectors';\nimport { RoutingProvider } from '../routing/RoutingProvider';\nimport {\n validateRouteParameters,\n validateRouteBindings,\n} from '../routing/validation';\nimport { AppContextProvider } from './AppContext';\nimport { AppIdentityProxy } from '../apis/implementations/IdentityApi/AppIdentityProxy';\nimport {\n AppComponents,\n AppConfigLoader,\n AppContext,\n AppOptions,\n BackstageApp,\n} from './types';\nimport { AppThemeProvider } from './AppThemeProvider';\nimport { defaultConfigLoader } from './defaultConfigLoader';\nimport { ApiRegistry } from '../apis/system/ApiRegistry';\nimport { resolveRouteBindings } from './resolveRouteBindings';\nimport { isReactRouterBeta } from './isReactRouterBeta';\nimport { InternalAppContext } from './InternalAppContext';\nimport { AppRouter, getBasePath } from './AppRouter';\nimport { AppLanguageSelector } from '../apis/implementations/AppLanguageApi';\nimport { I18nextTranslationApi } from '../apis/implementations/TranslationApi';\nimport { overrideBaseUrlConfigs } from './overrideBaseUrlConfigs';\nimport { isProtectedApp } from './isProtectedApp';\n\ntype CompatiblePlugin =\n | BackstagePlugin\n | (Omit<BackstagePlugin, 'getFeatureFlags'> & {\n output(): Array<{ type: 'feature-flag'; name: string }>;\n });\n\nfunction useConfigLoader(\n configLoader: AppConfigLoader | undefined,\n components: AppComponents,\n appThemeApi: AppThemeApi,\n): { api: ConfigApi } | { node: JSX.Element } {\n // Keeping this synchronous when a config loader isn't set simplifies tests a lot\n const hasConfig = Boolean(configLoader);\n const config = useAsync(configLoader || (() => Promise.resolve([])));\n\n let noConfigNode = undefined;\n\n if (hasConfig && config.loading) {\n const { Progress } = components;\n noConfigNode = <Progress />;\n } else if (config.error) {\n const { BootErrorPage } = components;\n noConfigNode = <BootErrorPage step=\"load-config\" error={config.error} />;\n }\n\n const { ThemeProvider = AppThemeProvider } = components;\n\n // Before the config is loaded we can't use a router, so exit early\n if (noConfigNode) {\n return {\n node: (\n <ApiProvider apis={ApiRegistry.with(appThemeApiRef, appThemeApi)}>\n <ThemeProvider>{noConfigNode}</ThemeProvider>\n </ApiProvider>\n ),\n };\n }\n\n const configReader = ConfigReader.fromConfigs(\n config.value?.length ? overrideBaseUrlConfigs(config.value) : [],\n );\n\n return { api: configReader };\n}\n\nclass AppContextImpl implements AppContext {\n constructor(private readonly app: AppManager) {}\n\n getPlugins(): BackstagePlugin[] {\n return this.app.getPlugins();\n }\n\n getSystemIcon(key: string): IconComponent | undefined {\n return this.app.getSystemIcon(key);\n }\n\n getSystemIcons(): Record<string, IconComponent> {\n return this.app.getSystemIcons();\n }\n\n getComponents(): AppComponents {\n return this.app.getComponents();\n }\n}\n\nexport class AppManager implements BackstageApp {\n private apiHolder?: ApiHolder;\n private configApi?: ConfigApi;\n\n private readonly apis: Iterable<AnyApiFactory>;\n private readonly icons: NonNullable<AppOptions['icons']>;\n private readonly plugins: Set<CompatiblePlugin>;\n private readonly featureFlags: (FeatureFlag &\n Omit<FeatureFlag, 'pluginId'>)[];\n private readonly components: AppComponents;\n private readonly themes: AppTheme[];\n private readonly configLoader?: AppConfigLoader;\n private readonly defaultApis: Iterable<AnyApiFactory>;\n private readonly bindRoutes: AppOptions['bindRoutes'];\n private readonly appLanguageApi: AppLanguageApi;\n private readonly translationResources: Array<\n TranslationResource | TranslationMessages\n >;\n\n private readonly appIdentityProxy = new AppIdentityProxy();\n private readonly apiFactoryRegistry: ApiFactoryRegistry;\n\n constructor(options: AppOptions) {\n this.apis = options.apis ?? [];\n this.icons = options.icons;\n this.plugins = new Set((options.plugins as CompatiblePlugin[]) ?? []);\n this.featureFlags = options.featureFlags ?? [];\n this.components = options.components;\n this.themes = options.themes as AppTheme[];\n this.configLoader = options.configLoader ?? defaultConfigLoader;\n this.defaultApis = options.defaultApis ?? [];\n this.bindRoutes = options.bindRoutes;\n this.apiFactoryRegistry = new ApiFactoryRegistry();\n this.appLanguageApi = AppLanguageSelector.createWithStorage({\n defaultLanguage: options.__experimentalTranslations?.defaultLanguage,\n availableLanguages:\n options.__experimentalTranslations?.availableLanguages,\n });\n this.translationResources =\n options.__experimentalTranslations?.resources ?? [];\n }\n\n getPlugins(): BackstagePlugin[] {\n return Array.from(this.plugins) as BackstagePlugin[];\n }\n\n getSystemIcon(key: string): IconComponent | undefined {\n return this.icons[key];\n }\n\n getSystemIcons(): Record<string, IconComponent> {\n return this.icons;\n }\n\n getComponents(): AppComponents {\n return this.components;\n }\n\n createRoot(element: JSX.Element): ComponentType<PropsWithChildren<{}>> {\n const AppProvider = this.getProvider();\n const AppRoot = () => {\n return <AppProvider>{element}</AppProvider>;\n };\n return AppRoot;\n }\n\n #getProviderCalled = false;\n getProvider(): ComponentType<PropsWithChildren<{}>> {\n if (this.#getProviderCalled) {\n throw new Error(\n 'app.getProvider() or app.createRoot() has already been called, and can only be called once',\n );\n }\n this.#getProviderCalled = true;\n\n const appContext = new AppContextImpl(this);\n\n // We only bind and validate routes once\n let routeBindings: ReturnType<typeof resolveRouteBindings>;\n // Store and keep throwing the same error if we encounter one\n let routeValidationError: Error | undefined = undefined;\n\n const Provider = ({ children }: PropsWithChildren<{}>) => {\n const needsFeatureFlagRegistrationRef = useRef(true);\n const appThemeApi = useMemo(\n () => AppThemeSelector.createWithStorage(this.themes),\n [],\n );\n\n const { routing, featureFlags } = useMemo(() => {\n const usesReactRouterBeta = isReactRouterBeta();\n if (usesReactRouterBeta) {\n // eslint-disable-next-line no-console\n console.warn(`\nDEPRECATION WARNING: React Router Beta is deprecated and support for it will be removed in a future release.\n Please migrate to use React Router v6 stable.\n See https://backstage.io/docs/tutorials/react-router-stable-migration\n`);\n }\n\n const result = traverseElementTree({\n root: children,\n discoverers: [childDiscoverer, routeElementDiscoverer],\n collectors: {\n routing: usesReactRouterBeta\n ? routingV1Collector\n : routingV2Collector,\n collectedPlugins: pluginCollector,\n featureFlags: featureFlagCollector,\n },\n });\n\n // TODO(Rugvip): Restructure the public API so that we can get an immediate view of\n // the app, rather than having to wait for the provider to render.\n // For now we need to push the additional plugins we find during\n // collection and then make sure we initialize things afterwards.\n result.collectedPlugins.forEach(plugin => this.plugins.add(plugin));\n this.verifyPlugins(this.plugins);\n\n // Initialize APIs once all plugins are available\n this.getApiHolder();\n return result;\n }, [children]);\n\n const loadedConfig = useConfigLoader(\n this.configLoader,\n this.components,\n appThemeApi,\n );\n\n const hasConfigApi = 'api' in loadedConfig;\n if (hasConfigApi) {\n const { api } = loadedConfig as { api: Config };\n this.configApi = api;\n }\n\n if ('node' in loadedConfig) {\n // Loading or error\n return loadedConfig.node;\n }\n\n if (routeValidationError) {\n throw routeValidationError;\n } else if (!routeBindings) {\n try {\n routeBindings = resolveRouteBindings(\n this.bindRoutes,\n loadedConfig.api,\n this.plugins,\n );\n\n validateRouteParameters(routing.paths, routing.parents);\n validateRouteBindings(routeBindings, this.plugins);\n } catch (error) {\n routeValidationError = error;\n throw error;\n }\n }\n\n // We can't register feature flags just after the element traversal, because the\n // config API isn't available yet and implementations frequently depend on it.\n // Instead we make it happen immediately, to make sure all flags are available\n // for the first render.\n if (hasConfigApi && needsFeatureFlagRegistrationRef.current) {\n needsFeatureFlagRegistrationRef.current = false;\n\n const featureFlagsApi = this.getApiHolder().get(featureFlagsApiRef)!;\n\n if (featureFlagsApi) {\n for (const flag of this.featureFlags) {\n featureFlagsApi.registerFlag({\n ...flag,\n pluginId: '',\n });\n }\n for (const plugin of this.plugins.values()) {\n if ('getFeatureFlags' in plugin) {\n for (const flag of plugin.getFeatureFlags()) {\n featureFlagsApi.registerFlag({\n name: flag.name,\n pluginId: plugin.getId(),\n });\n }\n } else {\n for (const output of plugin.output()) {\n if (output.type === 'feature-flag') {\n featureFlagsApi.registerFlag({\n name: output.name,\n pluginId: plugin.getId(),\n });\n }\n }\n }\n }\n\n // Go through the featureFlags returned from the traversal and\n // register those now the configApi has been loaded\n const registeredFlags = featureFlagsApi.getRegisteredFlags();\n const flagNames = new Set(registeredFlags.map(f => f.name));\n for (const name of featureFlags) {\n // Prevents adding duplicate feature flags\n if (!flagNames.has(name)) {\n featureFlagsApi.registerFlag({ name, pluginId: '' });\n }\n }\n }\n }\n\n const { ThemeProvider = AppThemeProvider, Progress } = this.components;\n\n const apis = this.getApiHolder();\n\n if (isProtectedApp()) {\n const errorApi = apis.get(errorApiRef);\n const fetchApi = apis.get(fetchApiRef);\n const discoveryApi = apis.get(discoveryApiRef);\n if (!errorApi || !fetchApi || !discoveryApi) {\n throw new Error(\n 'App is running in protected mode but missing required APIs',\n );\n }\n this.appIdentityProxy.enableCookieAuth({\n errorApi,\n fetchApi,\n discoveryApi,\n });\n }\n\n return (\n <ApiProvider apis={apis}>\n <AppContextProvider appContext={appContext}>\n <ThemeProvider>\n <RoutingProvider\n routePaths={routing.paths}\n routeParents={routing.parents}\n routeObjects={routing.objects}\n routeBindings={routeBindings}\n basePath={getBasePath(loadedConfig.api)}\n >\n <InternalAppContext.Provider\n value={{\n routeObjects: routing.objects,\n appIdentityProxy: this.appIdentityProxy,\n }}\n >\n <Suspense fallback={<Progress />}>{children}</Suspense>\n </InternalAppContext.Provider>\n </RoutingProvider>\n </ThemeProvider>\n </AppContextProvider>\n </ApiProvider>\n );\n };\n return Provider;\n }\n\n getRouter(): ComponentType<PropsWithChildren<{}>> {\n return AppRouter;\n }\n\n private getApiHolder(): ApiHolder {\n if (this.apiHolder) {\n // Register additional plugins if they have been added.\n // Routes paths, objects and others are already updated in the provider when children of it change\n for (const plugin of this.plugins) {\n for (const factory of plugin.getApis()) {\n if (!this.apiFactoryRegistry.get(factory.api)) {\n this.apiFactoryRegistry.register('default', factory);\n }\n }\n }\n ApiResolver.validateFactories(\n this.apiFactoryRegistry,\n this.apiFactoryRegistry.getAllApis(),\n );\n return this.apiHolder;\n }\n this.apiFactoryRegistry.register('static', {\n api: appThemeApiRef,\n deps: {},\n factory: () => AppThemeSelector.createWithStorage(this.themes),\n });\n this.apiFactoryRegistry.register('static', {\n api: configApiRef,\n deps: {},\n factory: () => {\n if (!this.configApi) {\n throw new Error(\n 'Tried to access config API before config was loaded',\n );\n }\n return this.configApi;\n },\n });\n this.apiFactoryRegistry.register('static', {\n api: identityApiRef,\n deps: {},\n factory: () => this.appIdentityProxy,\n });\n this.apiFactoryRegistry.register('static', {\n api: appLanguageApiRef,\n deps: {},\n factory: () => this.appLanguageApi,\n });\n\n // The translation API is registered as a default API so that it can be overridden.\n // It will be up to the implementer of the new API to register translation resources.\n this.apiFactoryRegistry.register('default', {\n api: translationApiRef,\n deps: { languageApi: appLanguageApiRef },\n factory: ({ languageApi }) =>\n I18nextTranslationApi.create({\n languageApi,\n resources: this.translationResources,\n }),\n });\n\n // It's possible to replace the feature flag API, but since we must have at least\n // one implementation we add it here directly instead of through the defaultApis.\n this.apiFactoryRegistry.register('default', {\n api: featureFlagsApiRef,\n deps: {},\n factory: () => new LocalStorageFeatureFlags(),\n });\n for (const factory of this.defaultApis) {\n this.apiFactoryRegistry.register('default', factory);\n }\n\n for (const plugin of this.plugins) {\n for (const factory of plugin.getApis()) {\n if (!this.apiFactoryRegistry.register('default', factory)) {\n throw new Error(\n `Plugin ${plugin.getId()} tried to register duplicate or forbidden API factory for ${\n factory.api\n }`,\n );\n }\n }\n }\n\n for (const factory of this.apis) {\n if (!this.apiFactoryRegistry.register('app', factory)) {\n throw new Error(\n `Duplicate or forbidden API factory for ${factory.api} in app`,\n );\n }\n }\n\n ApiResolver.validateFactories(\n this.apiFactoryRegistry,\n this.apiFactoryRegistry.getAllApis(),\n );\n\n this.apiHolder = new ApiResolver(this.apiFactoryRegistry);\n return this.apiHolder;\n }\n\n private verifyPlugins(plugins: Iterable<CompatiblePlugin>) {\n const pluginIds = new Set<string>();\n\n for (const plugin of plugins) {\n const id = plugin.getId();\n if (pluginIds.has(id)) {\n throw new Error(`Duplicate plugin found '${id}'`);\n }\n pluginIds.add(id);\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 {\n RouteRef,\n SubRouteRef,\n ExternalRouteRef,\n BackstagePlugin,\n AnyRoutes,\n AnyExternalRoutes,\n} from '@backstage/core-plugin-api';\nimport { AppOptions, AppRouteBinder } from './types';\nimport { Config } from '@backstage/config';\nimport { JsonObject } from '@backstage/types';\n\n/** @internal */\nexport function collectRouteIds(\n plugins: Iterable<\n Pick<\n BackstagePlugin<AnyRoutes, AnyExternalRoutes>,\n 'getId' | 'routes' | 'externalRoutes'\n >\n >,\n) {\n const routesById = new Map<string, RouteRef | SubRouteRef>();\n const externalRoutesById = new Map<string, ExternalRouteRef>();\n\n for (const plugin of plugins) {\n for (const [name, ref] of Object.entries(plugin.routes ?? {})) {\n const refId = `${plugin.getId()}.${name}`;\n if (routesById.has(refId)) {\n throw new Error(`Unexpected duplicate route '${refId}'`);\n }\n\n routesById.set(refId, ref);\n }\n for (const [name, ref] of Object.entries(plugin.externalRoutes ?? {})) {\n const refId = `${plugin.getId()}.${name}`;\n if (externalRoutesById.has(refId)) {\n throw new Error(`Unexpected duplicate external route '${refId}'`);\n }\n\n externalRoutesById.set(refId, ref);\n }\n }\n\n return { routes: routesById, externalRoutes: externalRoutesById };\n}\n\n/** @internal */\nexport function resolveRouteBindings(\n bindRoutes: AppOptions['bindRoutes'],\n config: Config,\n plugins: Iterable<\n Pick<\n BackstagePlugin<AnyRoutes, AnyExternalRoutes>,\n 'getId' | 'routes' | 'externalRoutes'\n >\n >,\n) {\n const routesById = collectRouteIds(plugins);\n const result = new Map<ExternalRouteRef, RouteRef | SubRouteRef>();\n const disabledExternalRefs = new Set<ExternalRouteRef>();\n\n // Perform callback bindings first with highest priority\n if (bindRoutes) {\n const bind: AppRouteBinder = (\n externalRoutes,\n targetRoutes: { [name: string]: RouteRef | SubRouteRef },\n ) => {\n for (const [key, value] of Object.entries(targetRoutes)) {\n const externalRoute = externalRoutes[key];\n if (!externalRoute) {\n throw new Error(`Key ${key} is not an existing external route`);\n }\n if (!value && !externalRoute.optional) {\n throw new Error(\n `External route ${key} is required but was ${\n value === false ? 'disabled' : 'not provided'\n }`,\n );\n }\n if (value) {\n result.set(externalRoute, value);\n } else if (value === false) {\n disabledExternalRefs.add(externalRoute);\n }\n }\n };\n bindRoutes({ bind });\n }\n\n // Then perform config based bindings with lower priority\n const bindings = config\n .getOptionalConfig('app.routes.bindings')\n ?.get<JsonObject>();\n if (bindings) {\n for (const [externalRefId, targetRefId] of Object.entries(bindings)) {\n if (!isValidTargetRefId(targetRefId)) {\n throw new Error(\n `Invalid config at app.routes.bindings['${externalRefId}'], value must be a non-empty string or false`,\n );\n }\n\n const externalRef = routesById.externalRoutes.get(externalRefId);\n if (!externalRef) {\n throw new Error(\n `Invalid config at app.routes.bindings, '${externalRefId}' is not a valid external route`,\n );\n }\n\n // Skip if binding was already defined in code\n if (result.has(externalRef) || disabledExternalRefs.has(externalRef)) {\n continue;\n }\n\n if (targetRefId === false) {\n disabledExternalRefs.add(externalRef);\n } else {\n const targetRef = routesById.routes.get(targetRefId);\n if (!targetRef) {\n throw new Error(\n `Invalid config at app.routes.bindings['${externalRefId}'], '${targetRefId}' is not a valid route`,\n );\n }\n\n result.set(externalRef, targetRef);\n }\n }\n }\n\n // Finally fall back to attempting to map defaults, at lowest priority\n for (const externalRef of routesById.externalRoutes.values()) {\n if (!result.has(externalRef) && !disabledExternalRefs.has(externalRef)) {\n const defaultRefId =\n 'getDefaultTarget' in externalRef\n ? (externalRef.getDefaultTarget as () => string | undefined)()\n : undefined;\n if (defaultRefId) {\n const defaultRef = routesById.routes.get(defaultRefId);\n if (defaultRef) {\n result.set(externalRef, defaultRef);\n }\n }\n }\n }\n\n return result;\n}\n\nfunction isValidTargetRefId(value: unknown): value is string | false {\n if (value === false) {\n return true;\n }\n\n if (typeof value === 'string' && value) {\n return true;\n }\n\n return false;\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 BackstagePlugin,\n ExternalRouteRef,\n RouteRef,\n SubRouteRef,\n} from '@backstage/core-plugin-api';\nimport { joinPaths } from './helpers';\nimport { AnyRouteRef } from './types';\n\n// Validates that there is no duplication of route parameter names\nexport function validateRouteParameters(\n routePaths: Map<AnyRouteRef, string>,\n routeParents: Map<AnyRouteRef, AnyRouteRef | undefined>,\n) {\n const notLeafRoutes = new Set(routeParents.values());\n notLeafRoutes.delete(undefined);\n\n for (const route of routeParents.keys()) {\n if (notLeafRoutes.has(route)) {\n continue;\n }\n\n let currentRouteRef: AnyRouteRef | undefined = route;\n\n let fullPath = '';\n while (currentRouteRef) {\n const path = routePaths.get(currentRouteRef);\n if (path === undefined) {\n throw new Error(`No path for ${currentRouteRef}`);\n }\n fullPath = joinPaths(path, fullPath);\n currentRouteRef = routeParents.get(currentRouteRef);\n }\n\n const params = fullPath.match(/:(\\w+)/g);\n if (params) {\n for (let j = 0; j < params.length; j++) {\n for (let i = j + 1; i < params.length; i++) {\n if (params[i] === params[j]) {\n throw new Error(\n `Parameter ${params[i]} is duplicated in path ${fullPath}`,\n );\n }\n }\n }\n }\n }\n}\n\n// Validates that all non-optional external routes have been bound\nexport function validateRouteBindings(\n routeBindings: Map<ExternalRouteRef, RouteRef | SubRouteRef>,\n plugins: Iterable<\n Pick<\n BackstagePlugin<{}, Record<string, ExternalRouteRef>>,\n 'getId' | 'externalRoutes'\n >\n >,\n) {\n for (const plugin of plugins) {\n if (!plugin.externalRoutes) {\n continue;\n }\n\n for (const [name, externalRouteRef] of Object.entries(\n plugin.externalRoutes,\n )) {\n if (externalRouteRef.optional) {\n continue;\n }\n\n if (!routeBindings.has(externalRouteRef)) {\n throw new Error(\n `External route '${name}' of the '${plugin.getId()}' plugin must be bound to a target route. ` +\n 'See https://backstage.io/link?bind-routes for details.',\n );\n }\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\nexport function isProtectedApp() {\n const element = document.querySelector('meta[name=\"backstage-app-mode\"]');\n const appMode = element?.getAttribute('content') ?? 'public';\n return appMode === 'protected';\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 { ReactNode, useMemo } from 'react';\nimport { useRoutes } from 'react-router-dom';\nimport {\n attachComponentData,\n useApp,\n useElementFilter,\n} from '@backstage/core-plugin-api';\nimport { isReactRouterBeta } from '../app/isReactRouterBeta';\n\nlet warned = false;\n\ntype RouteObject = {\n path: string;\n element: ReactNode;\n children?: RouteObject[];\n};\n\n/**\n * Props for the {@link FlatRoutes} component.\n *\n * @public\n */\nexport type FlatRoutesProps = {\n children: ReactNode;\n};\n\n/**\n * A wrapper around a set of routes.\n *\n * @remarks\n *\n * The root of the routing hierarchy in your app should use this component,\n * instead of the one from `react-router-dom`. This ensures that all of the\n * plugin route and utility API wiring happens under the hood.\n *\n * @public\n */\nexport const FlatRoutes = (props: FlatRoutesProps): JSX.Element | null => {\n const app = useApp();\n const { NotFoundErrorPage } = app.getComponents();\n const isBeta = useMemo(() => isReactRouterBeta(), []);\n const routes = useElementFilter(props.children, elements =>\n elements\n .getElements<{\n path?: string;\n element?: ReactNode;\n children?: ReactNode;\n }>()\n .flatMap<RouteObject>(child => {\n let path = child.props.path;\n\n // TODO(Rugvip): Work around plugins registering empty paths, remove once deprecated routes are gone\n if (path === '') {\n return [];\n }\n path = path?.replace(/\\/\\*$/, '') ?? '/';\n\n let element = isBeta ? child : child.props.element;\n if (!isBeta && !element) {\n element = child;\n if (!warned && process.env.NODE_ENV !== 'test') {\n // eslint-disable-next-line no-console\n console.warn(\n 'DEPRECATION WARNING: All elements within <FlatRoutes> must be of type <Route> with an element prop. ' +\n 'Existing usages of <Navigate key=[path] to=[to] /> should be replaced with <Route path=[path] element={<Navigate to=[to] />} />.',\n );\n warned = true;\n }\n }\n\n return [\n {\n // Each route matches any sub route, except for the explicit root path\n path,\n element,\n children: child.props.children\n ? [\n // These are the children of each route, which we all add in under a catch-all\n // subroute in order to make them available to `useOutlet`\n {\n path: path === '/' ? '/' : '*', // The root path must require an exact match\n element: child.props.children,\n },\n ]\n : undefined,\n },\n ];\n })\n // Routes are sorted to work around a bug where prefixes are unexpectedly matched\n // TODO(Rugvip): This can be removed once react-router v6 beta is no longer supported\n .sort((a, b) => b.path.localeCompare(a.path))\n .map(obj => ({ ...obj, path: obj.path === '/' ? '/' : `${obj.path}/*` })),\n );\n\n // TODO(Rugvip): Possibly add a way to skip this, like a noNotFoundPage prop\n const withNotFound = [\n ...routes,\n {\n path: '*',\n element: <NotFoundErrorPage />,\n },\n ];\n\n return useRoutes(withNotFound);\n};\n\nattachComponentData(FlatRoutes, 'core.type', 'FlatRoutes');\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\nexport const pluginId = 'catalog';\n","/*\n * Copyright 2025 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\n// ******************************************************************\n// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *\n// ******************************************************************\nimport { DiscoveryApi } from '../types/discovery';\nimport { FetchApi } from '../types/fetch';\nimport crossFetch from 'cross-fetch';\nimport { pluginId } from '../pluginId';\nimport * as parser from 'uri-template';\nimport { EntitiesBatchResponse } from '../models/EntitiesBatchResponse.model';\nimport { EntitiesQueryResponse } from '../models/EntitiesQueryResponse.model';\nimport { Entity } from '../models/Entity.model';\nimport { EntityAncestryResponse } from '../models/EntityAncestryResponse.model';\nimport { EntityFacetsResponse } from '../models/EntityFacetsResponse.model';\nimport { GetEntitiesByRefsRequest } from '../models/GetEntitiesByRefsRequest.model';\nimport { RefreshEntityRequest } from '../models/RefreshEntityRequest.model';\nimport { ValidateEntityRequest } from '../models/ValidateEntityRequest.model';\nimport { AnalyzeLocationRequest } from '../models/AnalyzeLocationRequest.model';\nimport { AnalyzeLocationResponse } from '../models/AnalyzeLocationResponse.model';\nimport { CreateLocation201Response } from '../models/CreateLocation201Response.model';\nimport { CreateLocationRequest } from '../models/CreateLocationRequest.model';\nimport { GetLocations200ResponseInner } from '../models/GetLocations200ResponseInner.model';\nimport { Location } from '../models/Location.model';\n\n/**\n * Wraps the Response type to convey a type on the json call.\n *\n * @public\n */\nexport type TypedResponse<T> = Omit<Response, 'json'> & {\n json: () => Promise<T>;\n};\n\n/**\n * Options you can pass into a request for additional information.\n *\n * @public\n */\nexport interface RequestOptions {\n token?: string;\n}\n/**\n * @public\n */\nexport type DeleteEntityByUid = {\n path: {\n uid: string;\n };\n};\n/**\n * @public\n */\nexport type GetEntities = {\n query: {\n fields?: Array<string>;\n limit?: number;\n filter?: Array<string>;\n offset?: number;\n after?: string;\n order?: Array<string>;\n };\n};\n/**\n * @public\n */\nexport type GetEntitiesByQuery = {\n query: {\n fields?: Array<string>;\n limit?: number;\n offset?: number;\n orderField?: Array<string>;\n cursor?: string;\n filter?: Array<string>;\n fullTextFilterTerm?: string;\n fullTextFilterFields?: Array<string>;\n };\n};\n/**\n * @public\n */\nexport type GetEntitiesByRefs = {\n body: GetEntitiesByRefsRequest;\n query: {\n filter?: Array<string>;\n };\n};\n/**\n * @public\n */\nexport type GetEntityAncestryByName = {\n path: {\n kind: string;\n namespace: string;\n name: string;\n };\n};\n/**\n * @public\n */\nexport type GetEntityByName = {\n path: {\n kind: string;\n namespace: string;\n name: string;\n };\n};\n/**\n * @public\n */\nexport type GetEntityByUid = {\n path: {\n uid: string;\n };\n};\n/**\n * @public\n */\nexport type GetEntityFacets = {\n query: {\n facet: Array<string>;\n filter?: Array<string>;\n };\n};\n/**\n * @public\n */\nexport type RefreshEntity = {\n body: RefreshEntityRequest;\n};\n/**\n * @public\n */\nexport type ValidateEntity = {\n body: ValidateEntityRequest;\n};\n/**\n * @public\n */\nexport type AnalyzeLocation = {\n body: AnalyzeLocationRequest;\n};\n/**\n * @public\n */\nexport type CreateLocation = {\n body: CreateLocationRequest;\n query: {\n dryRun?: string;\n };\n};\n/**\n * @public\n */\nexport type DeleteLocation = {\n path: {\n id: string;\n };\n};\n/**\n * @public\n */\nexport type GetLocation = {\n path: {\n id: string;\n };\n};\n/**\n * @public\n */\nexport type GetLocationByEntity = {\n path: {\n kind: string;\n namespace: string;\n name: string;\n };\n};\n/**\n * @public\n */\nexport type GetLocations = {};\n\n/**\n * @public\n */\nexport class DefaultApiClient {\n private readonly discoveryApi: DiscoveryApi;\n private readonly fetchApi: FetchApi;\n\n constructor(options: {\n discoveryApi: { getBaseUrl(pluginId: string): Promise<string> };\n fetchApi?: { fetch: typeof fetch };\n }) {\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi || { fetch: crossFetch };\n }\n\n /**\n * Delete a single entity by UID.\n * @param uid -\n */\n public async deleteEntityByUid(\n // @ts-ignore\n request: DeleteEntityByUid,\n options?: RequestOptions,\n ): Promise<TypedResponse<void>> {\n const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);\n\n const uriTemplate = `/entities/by-uid/{uid}`;\n\n const uri = parser.parse(uriTemplate).expand({\n uid: request.path.uid,\n });\n\n return await this.fetchApi.fetch(`${baseUrl}${uri}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'DELETE',\n });\n }\n\n /**\n * Get all entities matching a given filter.\n * @param fields - By default the full entities are returned, but you can pass in a &#x60;fields&#x60; query\nparameter which selects what parts of the entity data to retain. This makes the\nresponse smaller and faster to transfer, and may allow the catalog to perform\nmore efficient queries.\n\nThe query parameter value is a comma separated list of simplified JSON paths\nlike above. Each path corresponds to the key of either a value, or of a subtree\nroot that you want to keep in the output. The rest is pruned away. For example,\nspecifying &#x60;?fields&#x3D;metadata.name,metadata.annotations,spec&#x60; retains only the\n&#x60;name&#x60; and &#x60;annotations&#x60; fields of the &#x60;metadata&#x60; of each entity (it&#39;ll be an\nobject with at most two keys), keeps the entire &#x60;spec&#x60; unchanged, and cuts out\nall other roots such as &#x60;relations&#x60;.\n\nSome more real world usable examples:\n\n- Return only enough data to form the full ref of each entity:\n\n &#x60;/entities/by-query?fields&#x3D;kind,metadata.namespace,metadata.name&#x60;\n\n * @param limit - Number of records to return in the response.\n * @param filter - You can pass in one or more filter sets that get matched against each entity.\nEach filter set is a number of conditions that all have to match for the\ncondition to be true (conditions effectively have an AND between them). At least\none filter set has to be true for the entity to be part of the result set\n(filter sets effectively have an OR between them).\n\nExample:\n\n&#x60;&#x60;&#x60;text\n/entities/by-query?filter&#x3D;kind&#x3D;user,metadata.namespace&#x3D;default&amp;filter&#x3D;kind&#x3D;group,spec.type\n\n Return entities that match\n\n Filter set 1:\n Condition 1: kind &#x3D; user\n AND\n Condition 2: metadata.namespace &#x3D; default\n\n OR\n\n Filter set 2:\n Condition 1: kind &#x3D; group\n AND\n Condition 2: spec.type exists\n&#x60;&#x60;&#x60;\n\nEach condition is either on the form &#x60;&lt;key&gt;&#x60;, or on the form &#x60;&lt;key&gt;&#x3D;&lt;value&gt;&#x60;.\nThe first form asserts on the existence of a certain key (with any value), and\nthe second asserts that the key exists and has a certain value. All checks are\nalways case _insensitive_.\n\nIn all cases, the key is a simplified JSON path in a given piece of entity data.\nEach part of the path is a key of an object, and the traversal also descends\nthrough arrays. There are two special forms:\n\n- Array items that are simple value types (such as strings) match on a key-value\n pair where the key is the item as a string, and the value is the string &#x60;true&#x60;\n- Relations can be matched on a &#x60;relations.&lt;type&gt;&#x3D;&lt;targetRef&gt;&#x60; form\n\nLet&#39;s look at a simplified example to illustrate the concept:\n\n&#x60;&#x60;&#x60;json\n{\n &quot;a&quot;: {\n &quot;b&quot;: [&quot;c&quot;, { &quot;d&quot;: 1 }],\n &quot;e&quot;: 7\n }\n}\n&#x60;&#x60;&#x60;\n\nThis would match any one of the following conditions:\n\n- &#x60;a&#x60;\n- &#x60;a.b&#x60;\n- &#x60;a.b.c&#x60;\n- &#x60;a.b.c&#x3D;true&#x60;\n- &#x60;a.b.d&#x60;\n- &#x60;a.b.d&#x3D;1&#x60;\n- &#x60;a.e&#x60;\n- &#x60;a.e&#x3D;7&#x60;\n\nSome more real world usable examples:\n\n- Return all orphaned entities:\n\n &#x60;/entities/by-query?filter&#x3D;metadata.annotations.backstage.io/orphan&#x3D;true&#x60;\n\n- Return all users and groups:\n\n &#x60;/entities/by-query?filter&#x3D;kind&#x3D;user&amp;filter&#x3D;kind&#x3D;group&#x60;\n\n- Return all service components:\n\n &#x60;/entities/by-query?filter&#x3D;kind&#x3D;component,spec.type&#x3D;service&#x60;\n\n- Return all entities with the &#x60;java&#x60; tag:\n\n &#x60;/entities/by-query?filter&#x3D;metadata.tags.java&#x60;\n\n- Return all users who are members of the &#x60;ops&#x60; group (note that the full\n [reference](references.md) of the group is used):\n\n &#x60;/entities/by-query?filter&#x3D;kind&#x3D;user,relations.memberof&#x3D;group:default/ops&#x60;\n\n * @param offset - Number of records to skip in the query page.\n * @param after - Pointer to the previous page of results.\n * @param order - \n */\n public async getEntities(\n // @ts-ignore\n request: GetEntities,\n options?: RequestOptions,\n ): Promise<TypedResponse<Array<Entity>>> {\n const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);\n\n const uriTemplate = `/entities{?fields,limit,filter*,offset,after,order*}`;\n\n const uri = parser.parse(uriTemplate).expand({\n ...request.query,\n });\n\n return await this.fetchApi.fetch(`${baseUrl}${uri}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'GET',\n });\n }\n\n /**\n * Search for entities by a given query.\n * @param fields - By default the full entities are returned, but you can pass in a &#x60;fields&#x60; query\nparameter which selects what parts of the entity data to retain. This makes the\nresponse smaller and faster to transfer, and may allow the catalog to perform\nmore efficient queries.\n\nThe query parameter value is a comma separated list of simplified JSON paths\nlike above. Each path corresponds to the key of either a value, or of a subtree\nroot that you want to keep in the output. The rest is pruned away. For example,\nspecifying &#x60;?fields&#x3D;metadata.name,metadata.annotations,spec&#x60; retains only the\n&#x60;name&#x60; and &#x60;annotations&#x60; fields of the &#x60;metadata&#x60; of each entity (it&#39;ll be an\nobject with at most two keys), keeps the entire &#x60;spec&#x60; unchanged, and cuts out\nall other roots such as &#x60;relations&#x60;.\n\nSome more real world usable examples:\n\n- Return only enough data to form the full ref of each entity:\n\n &#x60;/entities/by-query?fields&#x3D;kind,metadata.namespace,metadata.name&#x60;\n\n * @param limit - Number of records to return in the response.\n * @param offset - Number of records to skip in the query page.\n * @param orderField - By default the entities are returned ordered by their internal uid. You can\ncustomize the &#x60;orderField&#x60; query parameters to affect that ordering.\n\nFor example, to return entities by their name:\n\n&#x60;/entities/by-query?orderField&#x3D;metadata.name,asc&#x60;\n\nEach parameter can be followed by &#x60;asc&#x60; for ascending lexicographical order or\n&#x60;desc&#x60; for descending (reverse) lexicographical order.\n\n * @param cursor - You may pass the &#x60;cursor&#x60; query parameters to perform cursor based pagination\nthrough the set of entities. The value of &#x60;cursor&#x60; will be returned in the response, under the &#x60;pageInfo&#x60; property:\n\n&#x60;&#x60;&#x60;json\n &quot;pageInfo&quot;: {\n &quot;nextCursor&quot;: &quot;a-cursor&quot;,\n &quot;prevCursor&quot;: &quot;another-cursor&quot;\n }\n&#x60;&#x60;&#x60;\n\nIf &#x60;nextCursor&#x60; exists, it can be used to retrieve the next batch of entities. Following the same approach,\nif &#x60;prevCursor&#x60; exists, it can be used to retrieve the previous batch of entities.\n\n- [&#x60;filter&#x60;](#filtering), for selecting only a subset of all entities\n- [&#x60;fields&#x60;](#field-selection), for selecting only parts of the full data\n structure of each entity\n- &#x60;limit&#x60; for limiting the number of entities returned (20 is the default)\n- [&#x60;orderField&#x60;](#ordering), for deciding the order of the entities\n- &#x60;fullTextFilter&#x60;\n **NOTE**: [&#x60;filter&#x60;, &#x60;orderField&#x60;, &#x60;fullTextFilter&#x60;] and &#x60;cursor&#x60; are mutually exclusive. This means that,\n it isn&#39;t possible to change any of [&#x60;filter&#x60;, &#x60;orderField&#x60;, &#x60;fullTextFilter&#x60;] when passing &#x60;cursor&#x60; as query parameters,\n as changing any of these properties will affect pagination. If any of &#x60;filter&#x60;, &#x60;orderField&#x60;, &#x60;fullTextFilter&#x60; is specified together with &#x60;cursor&#x60;, only the latter is taken into consideration.\n\n * @param filter - You can pass in one or more filter sets that get matched against each entity.\nEach filter set is a number of conditions that all have to match for the\ncondition to be true (conditions effectively have an AND between them). At least\none filter set has to be true for the entity to be part of the result set\n(filter sets effectively have an OR between them).\n\nExample:\n\n&#x60;&#x60;&#x60;text\n/entities/by-query?filter&#x3D;kind&#x3D;user,metadata.namespace&#x3D;default&amp;filter&#x3D;kind&#x3D;group,spec.type\n\n Return entities that match\n\n Filter set 1:\n Condition 1: kind &#x3D; user\n AND\n Condition 2: metadata.namespace &#x3D; default\n\n OR\n\n Filter set 2:\n Condition 1: kind &#x3D; group\n AND\n Condition 2: spec.type exists\n&#x60;&#x60;&#x60;\n\nEach condition is either on the form &#x60;&lt;key&gt;&#x60;, or on the form &#x60;&lt;key&gt;&#x3D;&lt;value&gt;&#x60;.\nThe first form asserts on the existence of a certain key (with any value), and\nthe second asserts that the key exists and has a certain value. All checks are\nalways case _insensitive_.\n\nIn all cases, the key is a simplified JSON path in a given piece of entity data.\nEach part of the path is a key of an object, and the traversal also descends\nthrough arrays. There are two special forms:\n\n- Array items that are simple value types (such as strings) match on a key-value\n pair where the key is the item as a string, and the value is the string &#x60;true&#x60;\n- Relations can be matched on a &#x60;relations.&lt;type&gt;&#x3D;&lt;targetRef&gt;&#x60; form\n\nLet&#39;s look at a simplified example to illustrate the concept:\n\n&#x60;&#x60;&#x60;json\n{\n &quot;a&quot;: {\n &quot;b&quot;: [&quot;c&quot;, { &quot;d&quot;: 1 }],\n &quot;e&quot;: 7\n }\n}\n&#x60;&#x60;&#x60;\n\nThis would match any one of the following conditions:\n\n- &#x60;a&#x60;\n- &#x60;a.b&#x60;\n- &#x60;a.b.c&#x60;\n- &#x60;a.b.c&#x3D;true&#x60;\n- &#x60;a.b.d&#x60;\n- &#x60;a.b.d&#x3D;1&#x60;\n- &#x60;a.e&#x60;\n- &#x60;a.e&#x3D;7&#x60;\n\nSome more real world usable examples:\n\n- Return all orphaned entities:\n\n &#x60;/entities/by-query?filter&#x3D;metadata.annotations.backstage.io/orphan&#x3D;true&#x60;\n\n- Return all users and groups:\n\n &#x60;/entities/by-query?filter&#x3D;kind&#x3D;user&amp;filter&#x3D;kind&#x3D;group&#x60;\n\n- Return all service components:\n\n &#x60;/entities/by-query?filter&#x3D;kind&#x3D;component,spec.type&#x3D;service&#x60;\n\n- Return all entities with the &#x60;java&#x60; tag:\n\n &#x60;/entities/by-query?filter&#x3D;metadata.tags.java&#x60;\n\n- Return all users who are members of the &#x60;ops&#x60; group (note that the full\n [reference](references.md) of the group is used):\n\n &#x60;/entities/by-query?filter&#x3D;kind&#x3D;user,relations.memberof&#x3D;group:default/ops&#x60;\n\n * @param fullTextFilterTerm - Text search term.\n * @param fullTextFilterFields - A comma separated list of fields to sort returned results by.\n */\n public async getEntitiesByQuery(\n // @ts-ignore\n request: GetEntitiesByQuery,\n options?: RequestOptions,\n ): Promise<TypedResponse<EntitiesQueryResponse>> {\n const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);\n\n const uriTemplate = `/entities/by-query{?fields,limit,offset,orderField*,cursor,filter*,fullTextFilterTerm,fullTextFilterFields}`;\n\n const uri = parser.parse(uriTemplate).expand({\n ...request.query,\n });\n\n return await this.fetchApi.fetch(`${baseUrl}${uri}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'GET',\n });\n }\n\n /**\n * Get a batch set of entities given an array of entityRefs.\n * @param filter - You can pass in one or more filter sets that get matched against each entity.\nEach filter set is a number of conditions that all have to match for the\ncondition to be true (conditions effectively have an AND between them). At least\none filter set has to be true for the entity to be part of the result set\n(filter sets effectively have an OR between them).\n\nExample:\n\n&#x60;&#x60;&#x60;text\n/entities/by-query?filter&#x3D;kind&#x3D;user,metadata.namespace&#x3D;default&amp;filter&#x3D;kind&#x3D;group,spec.type\n\n Return entities that match\n\n Filter set 1:\n Condition 1: kind &#x3D; user\n AND\n Condition 2: metadata.namespace &#x3D; default\n\n OR\n\n Filter set 2:\n Condition 1: kind &#x3D; group\n AND\n Condition 2: spec.type exists\n&#x60;&#x60;&#x60;\n\nEach condition is either on the form &#x60;&lt;key&gt;&#x60;, or on the form &#x60;&lt;key&gt;&#x3D;&lt;value&gt;&#x60;.\nThe first form asserts on the existence of a certain key (with any value), and\nthe second asserts that the key exists and has a certain value. All checks are\nalways case _insensitive_.\n\nIn all cases, the key is a simplified JSON path in a given piece of entity data.\nEach part of the path is a key of an object, and the traversal also descends\nthrough arrays. There are two special forms:\n\n- Array items that are simple value types (such as strings) match on a key-value\n pair where the key is the item as a string, and the value is the string &#x60;true&#x60;\n- Relations can be matched on a &#x60;relations.&lt;type&gt;&#x3D;&lt;targetRef&gt;&#x60; form\n\nLet&#39;s look at a simplified example to illustrate the concept:\n\n&#x60;&#x60;&#x60;json\n{\n &quot;a&quot;: {\n &quot;b&quot;: [&quot;c&quot;, { &quot;d&quot;: 1 }],\n &quot;e&quot;: 7\n }\n}\n&#x60;&#x60;&#x60;\n\nThis would match any one of the following conditions:\n\n- &#x60;a&#x60;\n- &#x60;a.b&#x60;\n- &#x60;a.b.c&#x60;\n- &#x60;a.b.c&#x3D;true&#x60;\n- &#x60;a.b.d&#x60;\n- &#x60;a.b.d&#x3D;1&#x60;\n- &#x60;a.e&#x60;\n- &#x60;a.e&#x3D;7&#x60;\n\nSome more real world usable examples:\n\n- Return all orphaned entities:\n\n &#x60;/entities/by-query?filter&#x3D;metadata.annotations.backstage.io/orphan&#x3D;true&#x60;\n\n- Return all users and groups:\n\n &#x60;/entities/by-query?filter&#x3D;kind&#x3D;user&amp;filter&#x3D;kind&#x3D;group&#x60;\n\n- Return all service components:\n\n &#x60;/entities/by-query?filter&#x3D;kind&#x3D;component,spec.type&#x3D;service&#x60;\n\n- Return all entities with the &#x60;java&#x60; tag:\n\n &#x60;/entities/by-query?filter&#x3D;metadata.tags.java&#x60;\n\n- Return all users who are members of the &#x60;ops&#x60; group (note that the full\n [reference](references.md) of the group is used):\n\n &#x60;/entities/by-query?filter&#x3D;kind&#x3D;user,relations.memberof&#x3D;group:default/ops&#x60;\n\n * @param getEntitiesByRefsRequest - \n */\n public async getEntitiesByRefs(\n // @ts-ignore\n request: GetEntitiesByRefs,\n options?: RequestOptions,\n ): Promise<TypedResponse<EntitiesBatchResponse>> {\n const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);\n\n const uriTemplate = `/entities/by-refs{?filter*}`;\n\n const uri = parser.parse(uriTemplate).expand({\n ...request.query,\n });\n\n return await this.fetchApi.fetch(`${baseUrl}${uri}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'POST',\n body: JSON.stringify(request.body),\n });\n }\n\n /**\n * Get an entity's ancestry by entity ref.\n * @param kind -\n * @param namespace -\n * @param name -\n */\n public async getEntityAncestryByName(\n // @ts-ignore\n request: GetEntityAncestryByName,\n options?: RequestOptions,\n ): Promise<TypedResponse<EntityAncestryResponse>> {\n const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);\n\n const uriTemplate = `/entities/by-name/{kind}/{namespace}/{name}/ancestry`;\n\n const uri = parser.parse(uriTemplate).expand({\n kind: request.path.kind,\n namespace: request.path.namespace,\n name: request.path.name,\n });\n\n return await this.fetchApi.fetch(`${baseUrl}${uri}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'GET',\n });\n }\n\n /**\n * Get an entity by an entity ref.\n * @param kind -\n * @param namespace -\n * @param name -\n */\n public async getEntityByName(\n // @ts-ignore\n request: GetEntityByName,\n options?: RequestOptions,\n ): Promise<TypedResponse<Entity>> {\n const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);\n\n const uriTemplate = `/entities/by-name/{kind}/{namespace}/{name}`;\n\n const uri = parser.parse(uriTemplate).expand({\n kind: request.path.kind,\n namespace: request.path.namespace,\n name: request.path.name,\n });\n\n return await this.fetchApi.fetch(`${baseUrl}${uri}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'GET',\n });\n }\n\n /**\n * Get a single entity by the UID.\n * @param uid -\n */\n public async getEntityByUid(\n // @ts-ignore\n request: GetEntityByUid,\n options?: RequestOptions,\n ): Promise<TypedResponse<Entity>> {\n const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);\n\n const uriTemplate = `/entities/by-uid/{uid}`;\n\n const uri = parser.parse(uriTemplate).expand({\n uid: request.path.uid,\n });\n\n return await this.fetchApi.fetch(`${baseUrl}${uri}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'GET',\n });\n }\n\n /**\n * Get all entity facets that match the given filters.\n * @param facet - \n * @param filter - You can pass in one or more filter sets that get matched against each entity.\nEach filter set is a number of conditions that all have to match for the\ncondition to be true (conditions effectively have an AND between them). At least\none filter set has to be true for the entity to be part of the result set\n(filter sets effectively have an OR between them).\n\nExample:\n\n&#x60;&#x60;&#x60;text\n/entities/by-query?filter&#x3D;kind&#x3D;user,metadata.namespace&#x3D;default&amp;filter&#x3D;kind&#x3D;group,spec.type\n\n Return entities that match\n\n Filter set 1:\n Condition 1: kind &#x3D; user\n AND\n Condition 2: metadata.namespace &#x3D; default\n\n OR\n\n Filter set 2:\n Condition 1: kind &#x3D; group\n AND\n Condition 2: spec.type exists\n&#x60;&#x60;&#x60;\n\nEach condition is either on the form &#x60;&lt;key&gt;&#x60;, or on the form &#x60;&lt;key&gt;&#x3D;&lt;value&gt;&#x60;.\nThe first form asserts on the existence of a certain key (with any value), and\nthe second asserts that the key exists and has a certain value. All checks are\nalways case _insensitive_.\n\nIn all cases, the key is a simplified JSON path in a given piece of entity data.\nEach part of the path is a key of an object, and the traversal also descends\nthrough arrays. There are two special forms:\n\n- Array items that are simple value types (such as strings) match on a key-value\n pair where the key is the item as a string, and the value is the string &#x60;true&#x60;\n- Relations can be matched on a &#x60;relations.&lt;type&gt;&#x3D;&lt;targetRef&gt;&#x60; form\n\nLet&#39;s look at a simplified example to illustrate the concept:\n\n&#x60;&#x60;&#x60;json\n{\n &quot;a&quot;: {\n &quot;b&quot;: [&quot;c&quot;, { &quot;d&quot;: 1 }],\n &quot;e&quot;: 7\n }\n}\n&#x60;&#x60;&#x60;\n\nThis would match any one of the following conditions:\n\n- &#x60;a&#x60;\n- &#x60;a.b&#x60;\n- &#x60;a.b.c&#x60;\n- &#x60;a.b.c&#x3D;true&#x60;\n- &#x60;a.b.d&#x60;\n- &#x60;a.b.d&#x3D;1&#x60;\n- &#x60;a.e&#x60;\n- &#x60;a.e&#x3D;7&#x60;\n\nSome more real world usable examples:\n\n- Return all orphaned entities:\n\n &#x60;/entities/by-query?filter&#x3D;metadata.annotations.backstage.io/orphan&#x3D;true&#x60;\n\n- Return all users and groups:\n\n &#x60;/entities/by-query?filter&#x3D;kind&#x3D;user&amp;filter&#x3D;kind&#x3D;group&#x60;\n\n- Return all service components:\n\n &#x60;/entities/by-query?filter&#x3D;kind&#x3D;component,spec.type&#x3D;service&#x60;\n\n- Return all entities with the &#x60;java&#x60; tag:\n\n &#x60;/entities/by-query?filter&#x3D;metadata.tags.java&#x60;\n\n- Return all users who are members of the &#x60;ops&#x60; group (note that the full\n [reference](references.md) of the group is used):\n\n &#x60;/entities/by-query?filter&#x3D;kind&#x3D;user,relations.memberof&#x3D;group:default/ops&#x60;\n\n */\n public async getEntityFacets(\n // @ts-ignore\n request: GetEntityFacets,\n options?: RequestOptions,\n ): Promise<TypedResponse<EntityFacetsResponse>> {\n const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);\n\n const uriTemplate = `/entity-facets{?facet*,filter*}`;\n\n const uri = parser.parse(uriTemplate).expand({\n ...request.query,\n });\n\n return await this.fetchApi.fetch(`${baseUrl}${uri}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'GET',\n });\n }\n\n /**\n * Refresh the entity related to entityRef.\n * @param refreshEntityRequest -\n */\n public async refreshEntity(\n // @ts-ignore\n request: RefreshEntity,\n options?: RequestOptions,\n ): Promise<TypedResponse<void>> {\n const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);\n\n const uriTemplate = `/refresh`;\n\n const uri = parser.parse(uriTemplate).expand({});\n\n return await this.fetchApi.fetch(`${baseUrl}${uri}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'POST',\n body: JSON.stringify(request.body),\n });\n }\n\n /**\n * Validate that a passed in entity has no errors in schema.\n * @param validateEntityRequest -\n */\n public async validateEntity(\n // @ts-ignore\n request: ValidateEntity,\n options?: RequestOptions,\n ): Promise<TypedResponse<void>> {\n const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);\n\n const uriTemplate = `/validate-entity`;\n\n const uri = parser.parse(uriTemplate).expand({});\n\n return await this.fetchApi.fetch(`${baseUrl}${uri}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'POST',\n body: JSON.stringify(request.body),\n });\n }\n\n /**\n * Validate a given location.\n * @param analyzeLocationRequest -\n */\n public async analyzeLocation(\n // @ts-ignore\n request: AnalyzeLocation,\n options?: RequestOptions,\n ): Promise<TypedResponse<AnalyzeLocationResponse>> {\n const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);\n\n const uriTemplate = `/analyze-location`;\n\n const uri = parser.parse(uriTemplate).expand({});\n\n return await this.fetchApi.fetch(`${baseUrl}${uri}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'POST',\n body: JSON.stringify(request.body),\n });\n }\n\n /**\n * Create a location for a given target.\n * @param createLocationRequest -\n * @param dryRun -\n */\n public async createLocation(\n // @ts-ignore\n request: CreateLocation,\n options?: RequestOptions,\n ): Promise<TypedResponse<CreateLocation201Response>> {\n const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);\n\n const uriTemplate = `/locations{?dryRun}`;\n\n const uri = parser.parse(uriTemplate).expand({\n ...request.query,\n });\n\n return await this.fetchApi.fetch(`${baseUrl}${uri}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'POST',\n body: JSON.stringify(request.body),\n });\n }\n\n /**\n * Delete a location by id.\n * @param id -\n */\n public async deleteLocation(\n // @ts-ignore\n request: DeleteLocation,\n options?: RequestOptions,\n ): Promise<TypedResponse<void>> {\n const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);\n\n const uriTemplate = `/locations/{id}`;\n\n const uri = parser.parse(uriTemplate).expand({\n id: request.path.id,\n });\n\n return await this.fetchApi.fetch(`${baseUrl}${uri}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'DELETE',\n });\n }\n\n /**\n * Get a location by id.\n * @param id -\n */\n public async getLocation(\n // @ts-ignore\n request: GetLocation,\n options?: RequestOptions,\n ): Promise<TypedResponse<Location>> {\n const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);\n\n const uriTemplate = `/locations/{id}`;\n\n const uri = parser.parse(uriTemplate).expand({\n id: request.path.id,\n });\n\n return await this.fetchApi.fetch(`${baseUrl}${uri}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'GET',\n });\n }\n\n /**\n * Get a location for entity.\n * @param kind -\n * @param namespace -\n * @param name -\n */\n public async getLocationByEntity(\n // @ts-ignore\n request: GetLocationByEntity,\n options?: RequestOptions,\n ): Promise<TypedResponse<Location>> {\n const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);\n\n const uriTemplate = `/locations/by-entity/{kind}/{namespace}/{name}`;\n\n const uri = parser.parse(uriTemplate).expand({\n kind: request.path.kind,\n namespace: request.path.namespace,\n name: request.path.name,\n });\n\n return await this.fetchApi.fetch(`${baseUrl}${uri}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'GET',\n });\n }\n\n /**\n * Get all locations\n */\n public async getLocations(\n // @ts-ignore\n request: GetLocations,\n options?: RequestOptions,\n ): Promise<TypedResponse<Array<GetLocations200ResponseInner>>> {\n const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);\n\n const uriTemplate = `/locations`;\n\n const uri = parser.parse(uriTemplate).expand({});\n\n return await this.fetchApi.fetch(`${baseUrl}${uri}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...(options?.token && { Authorization: `Bearer ${options?.token}` }),\n },\n method: 'GET',\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 {\n CompoundEntityRef,\n Entity,\n parseEntityRef,\n stringifyLocationRef,\n} from '@backstage/catalog-model';\nimport { ResponseError } from '@backstage/errors';\nimport {\n AddLocationRequest,\n AddLocationResponse,\n CATALOG_FILTER_EXISTS,\n CatalogApi,\n CatalogRequestOptions,\n EntityFilterQuery,\n GetEntitiesByRefsRequest,\n GetEntitiesByRefsResponse,\n GetEntitiesRequest,\n GetEntitiesResponse,\n GetEntityAncestorsRequest,\n GetEntityAncestorsResponse,\n GetEntityFacetsRequest,\n GetEntityFacetsResponse,\n GetLocationsResponse,\n Location,\n QueryEntitiesRequest,\n QueryEntitiesResponse,\n ValidateEntityResponse,\n} from './types/api';\nimport { isQueryEntitiesInitialRequest, splitRefsIntoChunks } from './utils';\nimport { DefaultApiClient, TypedResponse } from './schema/openapi';\nimport type {\n AnalyzeLocationRequest,\n AnalyzeLocationResponse,\n} from '@backstage/plugin-catalog-common';\n\n/**\n * A frontend and backend compatible client for communicating with the Backstage\n * software catalog.\n *\n * @public\n */\nexport class CatalogClient implements CatalogApi {\n private readonly apiClient: DefaultApiClient;\n\n constructor(options: {\n discoveryApi: { getBaseUrl(pluginId: string): Promise<string> };\n fetchApi?: { fetch: typeof fetch };\n }) {\n this.apiClient = new DefaultApiClient(options);\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntityAncestors}\n */\n async getEntityAncestors(\n request: GetEntityAncestorsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntityAncestorsResponse> {\n return await this.requestRequired(\n await this.apiClient.getEntityAncestryByName(\n { path: parseEntityRef(request.entityRef) },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.getLocations}\n */\n async getLocations(\n request?: {},\n options?: CatalogRequestOptions,\n ): Promise<GetLocationsResponse> {\n const res = await this.requestRequired(\n await this.apiClient.getLocations(request ?? {}, options),\n );\n return {\n items: res.map(item => item.data),\n };\n }\n\n /**\n * {@inheritdoc CatalogApi.getLocationById}\n */\n async getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.requestOptional(\n await this.apiClient.getLocation({ path: { id } }, options),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.getLocationByEntity}\n */\n async getLocationByEntity(\n entityRef: CompoundEntityRef | string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.requestOptional(\n await this.apiClient.getLocationByEntity(\n { path: parseEntityRef(entityRef) },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntities}\n */\n async getEntities(\n request?: GetEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntitiesResponse> {\n const {\n filter = [],\n fields = [],\n order,\n offset,\n limit,\n after,\n } = request ?? {};\n const encodedOrder = [];\n if (order) {\n for (const directive of [order].flat()) {\n if (directive) {\n encodedOrder.push(`${directive.order}:${directive.field}`);\n }\n }\n }\n\n const entities = await this.requestRequired(\n await this.apiClient.getEntities(\n {\n query: {\n fields,\n limit,\n filter: this.getFilterValue(filter),\n offset,\n after,\n order: order ? encodedOrder : undefined,\n },\n },\n options,\n ),\n );\n return { items: entities };\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntitiesByRefs}\n */\n async getEntitiesByRefs(\n request: GetEntitiesByRefsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntitiesByRefsResponse> {\n const getOneChunk = async (refs: string[]) => {\n const response = await this.apiClient.getEntitiesByRefs(\n {\n body: { entityRefs: refs, fields: request.fields },\n query: { filter: this.getFilterValue(request.filter) },\n },\n options,\n );\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n const body = (await response.json()) as {\n items: Array<Entity | null>;\n };\n return body.items.map(i => i ?? undefined);\n };\n\n let result: Array<Entity | undefined> | undefined;\n for (const refs of splitRefsIntoChunks(request.entityRefs)) {\n const entities = await getOneChunk(refs);\n if (!result) {\n result = entities;\n } else {\n result.push(...entities);\n }\n }\n\n return { items: result ?? [] };\n }\n\n /**\n * {@inheritdoc CatalogApi.queryEntities}\n */\n async queryEntities(\n request: QueryEntitiesRequest = {},\n options?: CatalogRequestOptions,\n ): Promise<QueryEntitiesResponse> {\n const params: Partial<\n Parameters<typeof this.apiClient.getEntitiesByQuery>[0]['query']\n > = {};\n\n if (isQueryEntitiesInitialRequest(request)) {\n const {\n fields = [],\n filter,\n limit,\n offset,\n orderFields,\n fullTextFilter,\n } = request;\n params.filter = this.getFilterValue(filter);\n\n if (limit !== undefined) {\n params.limit = limit;\n }\n if (offset !== undefined) {\n params.offset = offset;\n }\n if (orderFields !== undefined) {\n params.orderField = (\n Array.isArray(orderFields) ? orderFields : [orderFields]\n ).map(({ field, order }) => `${field},${order}`);\n }\n if (fields.length) {\n params.fields = fields;\n }\n\n const normalizedFullTextFilterTerm = fullTextFilter?.term?.trim();\n if (normalizedFullTextFilterTerm) {\n params.fullTextFilterTerm = normalizedFullTextFilterTerm;\n }\n if (fullTextFilter?.fields?.length) {\n params.fullTextFilterFields = fullTextFilter.fields;\n }\n } else {\n const { fields = [], limit, cursor } = request;\n\n params.cursor = cursor;\n if (limit !== undefined) {\n params.limit = limit;\n }\n if (fields.length) {\n params.fields = fields;\n }\n }\n\n return this.requestRequired(\n await this.apiClient.getEntitiesByQuery({ query: params }, options),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntityByRef}\n */\n async getEntityByRef(\n entityRef: string | CompoundEntityRef,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined> {\n return this.requestOptional(\n await this.apiClient.getEntityByName(\n {\n path: parseEntityRef(entityRef),\n },\n options,\n ),\n );\n }\n\n // NOTE(freben): When we deprecate getEntityByName from the interface, we may\n // still want to leave this implementation in place for quite some time\n // longer, to minimize the risk for breakages. Suggested date for removal:\n // August 2022\n /**\n * @deprecated Use getEntityByRef instead\n */\n async getEntityByName(\n compoundName: CompoundEntityRef,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined> {\n const { kind, namespace = 'default', name } = compoundName;\n return this.requestOptional(\n await this.apiClient.getEntityByName(\n { path: { kind, namespace, name } },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.refreshEntity}\n */\n async refreshEntity(entityRef: string, options?: CatalogRequestOptions) {\n const response = await this.apiClient.refreshEntity(\n { body: { entityRef } },\n options,\n );\n\n if (response.status !== 200) {\n throw await ResponseError.fromResponse(response);\n }\n }\n\n /**\n * {@inheritdoc CatalogApi.getEntityFacets}\n */\n async getEntityFacets(\n request: GetEntityFacetsRequest,\n options?: CatalogRequestOptions,\n ): Promise<GetEntityFacetsResponse> {\n const { filter = [], facets } = request;\n return await this.requestOptional(\n await this.apiClient.getEntityFacets(\n {\n query: { facet: facets, filter: this.getFilterValue(filter) },\n },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.addLocation}\n */\n async addLocation(\n request: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse> {\n const { type = 'url', target, dryRun } = request;\n\n const response = await this.apiClient.createLocation(\n {\n body: { type, target },\n query: { dryRun: dryRun ? 'true' : undefined },\n },\n options,\n );\n\n if (response.status !== 201) {\n throw await ResponseError.fromResponse(response);\n }\n\n const { location, entities, exists } = await response.json();\n\n if (!location) {\n throw new Error(`Location wasn't added: ${target}`);\n }\n\n return {\n location,\n entities,\n exists,\n };\n }\n\n /**\n * {@inheritdoc CatalogApi.getLocationByRef}\n */\n async getLocationByRef(\n locationRef: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n const all = await this.requestRequired(\n await this.apiClient.getLocations({}, options),\n );\n return all\n .map(r => r.data)\n .find(l => locationRef === stringifyLocationRef(l));\n }\n\n /**\n * {@inheritdoc CatalogApi.removeLocationById}\n */\n async removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n await this.apiClient.deleteLocation({ path: { id } }, options),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.removeEntityByUid}\n */\n async removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n await this.requestIgnored(\n await this.apiClient.deleteEntityByUid({ path: { uid } }, options),\n );\n }\n\n /**\n * {@inheritdoc CatalogApi.validateEntity}\n */\n async validateEntity(\n entity: Entity,\n locationRef: string,\n options?: CatalogRequestOptions,\n ): Promise<ValidateEntityResponse> {\n const response = await this.apiClient.validateEntity(\n { body: { entity, location: locationRef } },\n options,\n );\n\n if (response.ok) {\n return {\n valid: true,\n };\n }\n\n if (response.status !== 400) {\n throw await ResponseError.fromResponse(response);\n }\n\n const { errors = [] } = (await response.json()) as any;\n\n return {\n valid: false,\n errors,\n };\n }\n\n /**\n * {@inheritdoc CatalogApi.analyzeLocation}\n */\n async analyzeLocation(\n request: AnalyzeLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AnalyzeLocationResponse> {\n const response = await this.apiClient.analyzeLocation(\n {\n body: request,\n },\n options,\n );\n\n if (response.status !== 200) {\n throw await ResponseError.fromResponse(response);\n }\n\n return response.json() as Promise<AnalyzeLocationResponse>;\n }\n\n //\n // Private methods\n //\n\n private async requestIgnored(response: Response): Promise<void> {\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n }\n\n private async requestRequired<T>(response: TypedResponse<T>): Promise<T> {\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return response.json();\n }\n\n private async requestOptional(response: Response): Promise<any | undefined> {\n if (!response.ok) {\n if (response.status === 404) {\n return undefined;\n }\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n\n private getFilterValue(filter: EntityFilterQuery = []) {\n const filters: string[] = [];\n // filter param can occur multiple times, for example\n // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component'\n // the \"outer array\" defined by `filter` occurrences corresponds to \"anyOf\" filters\n // the \"inner array\" defined within a `filter` param corresponds to \"allOf\" filters\n for (const filterItem of [filter].flat()) {\n const filterParts: string[] = [];\n for (const [key, value] of Object.entries(filterItem)) {\n for (const v of [value].flat()) {\n if (v === CATALOG_FILTER_EXISTS) {\n filterParts.push(key);\n } else if (typeof v === 'string') {\n filterParts.push(`${key}=${v}`);\n }\n }\n }\n\n if (filterParts.length) {\n filters.push(filterParts.join(','));\n }\n }\n return filters;\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n QueryEntitiesCursorRequest,\n QueryEntitiesInitialRequest,\n} from './types/api';\n\nexport function isQueryEntitiesInitialRequest(\n request: QueryEntitiesInitialRequest,\n): request is QueryEntitiesInitialRequest {\n return !(request as QueryEntitiesCursorRequest).cursor;\n}\n\n/**\n * Takes a set of entity refs, and splits them into chunks (groups) such that\n * the total string length in each chunk does not exceed the default Express.js\n * request body limit of 100 kB (with some margin) when JSON encoded as an\n * array.\n */\nexport function splitRefsIntoChunks(\n refs: string[],\n options?: {\n // No chunk has more than this many refs, no matter what\n maxCountPerChunk?: number;\n // The total string length (taking the extraStringLengthPerRef into account)\n // of each chunk never exceeds this many characters, no matter what\n maxStringLengthPerChunk?: number;\n // Add this many characters to the length of each ref when calculating\n // (default is 3, since eacn array entry is surrounded by quotes and a\n // comma)\n extraStringLengthPerRef?: number;\n },\n): string[][] {\n if (!refs.length) {\n return [];\n }\n\n const {\n maxCountPerChunk = 1000,\n maxStringLengthPerChunk = 90 * 2 ** 10,\n extraStringLengthPerRef = 3,\n } = options ?? {};\n\n const chunks: string[][] = [];\n\n let currentChunkStart = 0;\n let currentChunkStringLength = 0;\n let currentChunkSize = 0;\n\n for (let i = 0; i < refs.length; ++i) {\n const refLength = refs[i].length + extraStringLengthPerRef;\n\n // always allow at least one element per chunk even in abnormal situations\n if (currentChunkSize > 0) {\n // emit chunk and start over if either the string length or the count\n // limit would be reached\n if (\n currentChunkStringLength + refLength > maxStringLengthPerChunk ||\n currentChunkSize + 1 > maxCountPerChunk\n ) {\n chunks.push(refs.slice(currentChunkStart, i));\n currentChunkStart = i;\n currentChunkStringLength = 0;\n currentChunkSize = 0;\n }\n }\n\n currentChunkStringLength += refLength;\n currentChunkSize += 1;\n }\n\n // emit whatever is left as the last chunk\n chunks.push(refs.slice(currentChunkStart, refs.length));\n\n return chunks;\n}\n","/*\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 { stringifyEntityRef } from '@backstage/catalog-model';\nimport { StorageApi } from '@backstage/core-plugin-api';\nimport { isArray, isString } from 'lodash';\n\n/**\n * Migrate the starred entities from the old format (entity:<kind>:<namespace>:<name>) from the\n * old storage location (/settings/starredEntities) to entity references in the new location\n * (/starredEntities/entityRefs).\n *\n * This will only be executed once since the old location is cleared.\n *\n * @param storageApi - the StorageApi to migrate\n */\nexport async function performMigrationToTheNewBucket({\n storageApi,\n}: {\n storageApi: StorageApi;\n}) {\n const source = storageApi.forBucket('settings');\n const target = storageApi.forBucket('starredEntities');\n\n const oldStarredEntities = source.snapshot('starredEntities').value;\n\n if (!isArray(oldStarredEntities)) {\n // nothing to do\n return;\n }\n const targetEntities = new Set(\n target.snapshot<string[]>('entityRefs').value ?? [],\n );\n\n oldStarredEntities\n .filter(isString)\n // extract the old format 'entity:<kind>:<namespace>:<name>'\n .map(old => old.split(':'))\n // check if the format is valid\n .filter(split => split.length === 4 && split[0] === 'entity')\n // convert to entity references\n .map(([_, kind, namespace, name]) =>\n stringifyEntityRef({ kind, namespace, name }),\n )\n .forEach(e => targetEntities.add(e));\n\n await target.set('entityRefs', Array.from(targetEntities));\n\n await source.remove('starredEntities');\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 { StorageApi } from '@backstage/core-plugin-api';\nimport { StarredEntitiesApi } from '@backstage/plugin-catalog-react';\nimport { Observable } from '@backstage/types';\nimport ObservableImpl from 'zen-observable';\nimport { performMigrationToTheNewBucket } from './migration';\n\n/**\n * Default implementation of the StarredEntitiesApi that is backed by the StorageApi.\n *\n * @public\n */\nexport class DefaultStarredEntitiesApi implements StarredEntitiesApi {\n private readonly settingsStore: StorageApi;\n private starredEntities: Set<string>;\n\n constructor(opts: { storageApi: StorageApi }) {\n // no need to await. The updated content will be caught by the observe$\n performMigrationToTheNewBucket(opts).then();\n\n this.settingsStore = opts.storageApi.forBucket('starredEntities');\n\n this.starredEntities = new Set(\n this.settingsStore.snapshot<string[]>('entityRefs').value ?? [],\n );\n\n this.settingsStore.observe$<string[]>('entityRefs').subscribe({\n next: next => {\n this.starredEntities = new Set(next.value ?? []);\n this.notifyChanges();\n },\n });\n }\n\n async toggleStarred(entityRef: string): Promise<void> {\n if (this.starredEntities.has(entityRef)) {\n this.starredEntities.delete(entityRef);\n } else {\n this.starredEntities.add(entityRef);\n }\n\n await this.settingsStore.set(\n 'entityRefs',\n Array.from(this.starredEntities),\n );\n }\n\n starredEntitie$(): Observable<Set<string>> {\n return this.observable;\n }\n\n private readonly subscribers = new Set<\n ZenObservable.SubscriptionObserver<Set<string>>\n >();\n\n private readonly observable = new ObservableImpl<Set<string>>(subscriber => {\n // forward the latest value\n subscriber.next(new Set(this.starredEntities));\n\n this.subscribers.add(subscriber);\n return () => {\n this.subscribers.delete(subscriber);\n };\n });\n\n private notifyChanges() {\n for (const subscription of this.subscribers) {\n subscription.next(new Set(this.starredEntities));\n }\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 */\n\n/**\n * Human friendly durations object.\n *\n * @public\n */\nexport type HumanDuration = {\n years?: number;\n months?: number;\n weeks?: number;\n days?: number;\n hours?: number;\n minutes?: number;\n seconds?: number;\n milliseconds?: number;\n};\n\n/**\n * Converts a {@link HumanDuration} to milliseconds.\n *\n * @public\n * @remarks\n *\n * Note that this conversion by definition is an approximation in the absence of\n * an anchor to a point in time and time zone, as the number of milliseconds is\n * not constant for many units. So the conversion assumes 365-day years, 30-day\n * months, and fixed 24-hour days.\n *\n * @param duration - A human friendly duration object.\n * @returns The number of approximate milliseconds that the duration represents.\n */\nexport function durationToMilliseconds(duration: HumanDuration): number {\n const {\n years = 0,\n months = 0,\n weeks = 0,\n days = 0,\n hours = 0,\n minutes = 0,\n seconds = 0,\n milliseconds = 0,\n } = duration;\n\n const totalDays = years * 365 + months * 30 + weeks * 7 + days;\n const totalHours = totalDays * 24 + hours;\n const totalMinutes = totalHours * 60 + minutes;\n const totalSeconds = totalMinutes * 60 + seconds;\n const totalMilliseconds = totalSeconds * 1000 + milliseconds;\n\n return totalMilliseconds;\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 { IconComponent } from '@backstage/core-plugin-api';\nimport { defaultEntityPresentation } from '@backstage/plugin-catalog-react';\nimport { HumanDuration } from '@backstage/types';\nimport ApartmentIcon from '@material-ui/icons/Apartment';\nimport CategoryIcon from '@material-ui/icons/Category';\nimport ExtensionIcon from '@material-ui/icons/Extension';\nimport FeaturedPlayListIcon from '@material-ui/icons/FeaturedPlayList';\nimport LocationOnIcon from '@material-ui/icons/LocationOn';\nimport MemoryIcon from '@material-ui/icons/Memory';\nimport PeopleIcon from '@material-ui/icons/People';\nimport PersonIcon from '@material-ui/icons/Person';\nimport StorageIcon from '@material-ui/icons/Storage';\nimport { DefaultEntityPresentationApiRenderer } from './DefaultEntityPresentationApi';\n\nexport const DEFAULT_CACHE_TTL: HumanDuration = { seconds: 10 };\n\nexport const DEFAULT_BATCH_DELAY: HumanDuration = { milliseconds: 50 };\n\nexport const DEFAULT_ICONS: Record<string, IconComponent> = {\n api: ExtensionIcon,\n component: MemoryIcon,\n system: CategoryIcon,\n resource: StorageIcon,\n domain: ApartmentIcon,\n location: LocationOnIcon,\n user: PersonIcon,\n group: PeopleIcon,\n template: FeaturedPlayListIcon,\n};\n\nexport function createDefaultRenderer(options: {\n async: boolean;\n}): DefaultEntityPresentationApiRenderer {\n return {\n async: options.async,\n\n render: ({ entityRef, entity, context }) => {\n const presentation = defaultEntityPresentation(\n entity || entityRef,\n context,\n );\n return {\n snapshot: presentation,\n loadEntity: options.async,\n };\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 */\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 { durationToMilliseconds, HumanDuration } from '@backstage/types';\nimport DataLoader from 'dataloader';\nimport ObservableImpl from 'zen-observable';\nimport {\n createDefaultRenderer,\n DEFAULT_BATCH_DELAY,\n DEFAULT_CACHE_TTL,\n DEFAULT_ICONS,\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// Simple expiry map for the data loader, which only expects a map that implements set, get, and delete and clear\nexport class ExpiryMap<K, V> extends Map<K, V> {\n #ttlMs: number;\n #timestamps: Map<K, number> = new Map();\n\n constructor(ttlMs: number) {\n super();\n this.#ttlMs = ttlMs;\n }\n\n set(key: K, value: V) {\n const result = super.set(key, value);\n this.#timestamps.set(key, Date.now());\n return result;\n }\n\n get(key: K) {\n if (!this.has(key)) {\n return undefined;\n }\n const timestamp = this.#timestamps.get(key)!;\n if (Date.now() - timestamp > this.#ttlMs) {\n this.delete(key);\n return undefined;\n }\n return super.get(key);\n }\n\n delete(key: K) {\n this.#timestamps.delete(key);\n return super.delete(key);\n }\n\n clear() {\n this.#timestamps.clear();\n return super.clear();\n }\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 fields: [\n 'kind',\n 'metadata.name',\n 'metadata.namespace',\n 'metadata.title',\n 'metadata.description',\n 'spec.profile.displayName',\n 'spec.type',\n ],\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","/*\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 { CatalogClient } from '@backstage/catalog-client';\nimport { Entity } from '@backstage/catalog-model';\nimport {\n catalogApiRef,\n entityPresentationApiRef,\n entityRouteRef,\n starredEntitiesApiRef,\n} from '@backstage/plugin-catalog-react';\nimport {\n createComponentRouteRef,\n createFromTemplateRouteRef,\n unregisterRedirectRouteRef,\n viewTechDocRouteRef,\n rootRouteRef,\n} from './routes';\nimport {\n createApiFactory,\n createComponentExtension,\n createPlugin,\n createRoutableExtension,\n discoveryApiRef,\n fetchApiRef,\n storageApiRef,\n} from '@backstage/core-plugin-api';\nimport {\n createSearchResultListItemExtension,\n SearchResultListItemExtensionProps,\n} from '@backstage/plugin-search-react';\nimport { DefaultStarredEntitiesApi } from './apis';\nimport { AboutCardProps } from './components/AboutCard';\nimport { DefaultCatalogPageProps } from './components/CatalogPage';\nimport { DependencyOfComponentsCardProps } from './components/DependencyOfComponentsCard';\nimport { DependsOnComponentsCardProps } from './components/DependsOnComponentsCard';\nimport { DependsOnResourcesCardProps } from './components/DependsOnResourcesCard';\nimport { HasComponentsCardProps } from './components/HasComponentsCard';\nimport { HasResourcesCardProps } from './components/HasResourcesCard';\nimport { HasSubcomponentsCardProps } from './components/HasSubcomponentsCard';\nimport { HasSubdomainsCardProps } from './components/HasSubdomainsCard';\nimport { HasSystemsCardProps } from './components/HasSystemsCard';\nimport { RelatedEntitiesCardProps } from './components/RelatedEntitiesCard';\nimport { CatalogSearchResultListItemProps } from './components/CatalogSearchResultListItem';\nimport { DefaultEntityPresentationApi } from './apis/EntityPresentationApi';\n\n/** @public */\nexport const catalogPlugin = createPlugin({\n id: 'catalog',\n apis: [\n createApiFactory({\n api: catalogApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ discoveryApi, fetchApi }) =>\n new CatalogClient({ discoveryApi, fetchApi }),\n }),\n createApiFactory({\n api: starredEntitiesApiRef,\n deps: { storageApi: storageApiRef },\n factory: ({ storageApi }) =>\n new DefaultStarredEntitiesApi({ storageApi }),\n }),\n createApiFactory({\n api: entityPresentationApiRef,\n deps: { catalogApi: catalogApiRef },\n factory: ({ catalogApi }) =>\n DefaultEntityPresentationApi.create({ catalogApi }),\n }),\n ],\n routes: {\n catalogIndex: rootRouteRef,\n catalogEntity: entityRouteRef,\n },\n externalRoutes: {\n createComponent: createComponentRouteRef,\n viewTechDoc: viewTechDocRouteRef,\n createFromTemplate: createFromTemplateRouteRef,\n unregisterRedirect: unregisterRedirectRouteRef,\n },\n});\n\n/** @public */\nexport const CatalogIndexPage: (props: DefaultCatalogPageProps) => JSX.Element =\n catalogPlugin.provide(\n createRoutableExtension({\n name: 'CatalogIndexPage',\n component: () =>\n import('./components/CatalogPage').then(m => m.CatalogPage),\n mountPoint: rootRouteRef,\n }),\n );\n\n/** @public */\nexport const CatalogEntityPage: () => JSX.Element = catalogPlugin.provide(\n createRoutableExtension({\n name: 'CatalogEntityPage',\n component: () =>\n import('./components/CatalogEntityPage').then(m => m.CatalogEntityPage),\n mountPoint: entityRouteRef,\n }),\n);\n\n/**\n * An example About card to show at the top of entity pages.\n *\n * @public\n * @remarks\n *\n * This card collects some high level information about the entity, but is just\n * an example component. Many organizations will want to replace it with a\n * custom card that is more tailored to their specific needs. The card itself is\n * not extremely customizable; feel free to make a copy of it as a starting\n * point if you like.\n */\nexport const EntityAboutCard: (props: AboutCardProps) => JSX.Element =\n catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityAboutCard',\n component: {\n lazy: () => import('./components/AboutCard').then(m => m.AboutCard),\n },\n }),\n );\n\n/** @public */\nexport const EntityLinksCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityLinksCard',\n component: {\n lazy: () =>\n import('./components/EntityLinksCard').then(m => m.EntityLinksCard),\n },\n }),\n);\n\n/** @public */\nexport const EntityLabelsCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityLabelsCard',\n component: {\n lazy: () =>\n import('./components/EntityLabelsCard').then(m => m.EntityLabelsCard),\n },\n }),\n);\n\n/** @public */\nexport const EntityHasSystemsCard: (props: HasSystemsCardProps) => JSX.Element =\n catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasSystemsCard',\n component: {\n lazy: () =>\n import('./components/HasSystemsCard').then(m => m.HasSystemsCard),\n },\n }),\n );\n\n/** @public */\nexport const EntityHasComponentsCard: (\n props: HasComponentsCardProps,\n) => JSX.Element = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasComponentsCard',\n component: {\n lazy: () =>\n import('./components/HasComponentsCard').then(m => m.HasComponentsCard),\n },\n }),\n);\n\n/** @public */\nexport const EntityHasSubcomponentsCard: (\n props: HasSubcomponentsCardProps,\n) => JSX.Element = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasSubcomponentsCard',\n component: {\n lazy: () =>\n import('./components/HasSubcomponentsCard').then(\n m => m.HasSubcomponentsCard,\n ),\n },\n }),\n);\n\n/** @public */\nexport const EntityHasSubdomainsCard: (\n props: HasSubdomainsCardProps,\n) => JSX.Element = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasSubdomainsCard',\n component: {\n lazy: () =>\n import('./components/HasSubdomainsCard').then(m => m.HasSubdomainsCard),\n },\n }),\n);\n\n/** @public */\nexport const EntityHasResourcesCard: (\n props: HasResourcesCardProps,\n) => JSX.Element = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasResourcesCard',\n component: {\n lazy: () =>\n import('./components/HasResourcesCard').then(m => m.HasResourcesCard),\n },\n }),\n);\n\n/** @public */\nexport const EntityDependsOnComponentsCard: (\n props: DependsOnComponentsCardProps,\n) => JSX.Element = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityDependsOnComponentsCard',\n component: {\n lazy: () =>\n import('./components/DependsOnComponentsCard').then(\n m => m.DependsOnComponentsCard,\n ),\n },\n }),\n);\n\n/** @public */\nexport const EntityDependencyOfComponentsCard: (\n props: DependencyOfComponentsCardProps,\n) => JSX.Element = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityDependencyOfComponentsCard',\n component: {\n lazy: () =>\n import('./components/DependencyOfComponentsCard').then(\n m => m.DependencyOfComponentsCard,\n ),\n },\n }),\n);\n\n/** @public */\nexport const EntityDependsOnResourcesCard: (\n props: DependsOnResourcesCardProps,\n) => JSX.Element = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityDependsOnResourcesCard',\n component: {\n lazy: () =>\n import('./components/DependsOnResourcesCard').then(\n m => m.DependsOnResourcesCard,\n ),\n },\n }),\n);\n\n/** @public */\nexport const RelatedEntitiesCard: <T extends Entity>(\n props: RelatedEntitiesCardProps<T>,\n) => JSX.Element = catalogPlugin.provide(\n createComponentExtension({\n name: 'RelatedEntitiesCard',\n component: {\n lazy: () =>\n import('./components/RelatedEntitiesCard').then(\n m => m.RelatedEntitiesCard,\n ),\n },\n }),\n);\n\n/** @public */\nexport const CatalogSearchResultListItem: (\n props: SearchResultListItemExtensionProps<CatalogSearchResultListItemProps>,\n) => JSX.Element | null = catalogPlugin.provide(\n createSearchResultListItemExtension({\n name: 'CatalogSearchResultListItem',\n component: () =>\n import('./components/CatalogSearchResultListItem').then(\n m => m.CatalogSearchResultListItem,\n ),\n predicate: result => result.type === 'software-catalog',\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 { CompoundEntityRef } from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport {\n scmIntegrationsApiRef,\n ScmIntegrationsApi,\n} from '@backstage/integration-react';\nimport {\n AnyApiFactory,\n configApiRef,\n createApiFactory,\n DiscoveryApi,\n discoveryApiRef,\n IdentityApi,\n identityApiRef,\n} from '@backstage/core-plugin-api';\nimport {\n SyncResult,\n TechDocsApi,\n techdocsApiRef,\n TechDocsStorageApi,\n techdocsStorageApiRef,\n} from '@backstage/plugin-techdocs-react';\n\n// TODO: Export type from plugin-techdocs and import this here\n// import { ParsedEntityId } from '@backstage/plugin-techdocs'\n\n/**\n * Note: Override TechDocs API to use local mkdocs server instead of techdocs-backend.\n */\n\nclass TechDocsDevStorageApi implements TechDocsStorageApi {\n public configApi: Config;\n public discoveryApi: DiscoveryApi;\n public identityApi: IdentityApi;\n\n constructor({\n configApi,\n discoveryApi,\n identityApi,\n }: {\n configApi: Config;\n discoveryApi: DiscoveryApi;\n identityApi: IdentityApi;\n }) {\n this.configApi = configApi;\n this.discoveryApi = discoveryApi;\n this.identityApi = identityApi;\n }\n\n async getApiOrigin() {\n return await this.discoveryApi.getBaseUrl('techdocs');\n }\n\n async getStorageUrl() {\n return `${await this.discoveryApi.getBaseUrl('techdocs')}/static/docs`;\n }\n\n async getBuilder() {\n return this.configApi.getOptionalString('techdocs.builder') || 'local';\n }\n\n async getEntityDocs(_entityId: CompoundEntityRef, path: string) {\n const apiOrigin = await this.getApiOrigin();\n // Irrespective of the entity, use mkdocs server to find the file for the path.\n const url = `${apiOrigin}/${path}`;\n\n const request = await fetch(\n `${url.endsWith('/') ? url : `${url}/`}index.html`,\n );\n\n if (request.status === 404) {\n throw new Error('Page not found');\n }\n\n return request.text();\n }\n\n async syncEntityDocs(_: CompoundEntityRef): Promise<SyncResult> {\n // this is just stub of this function as we don't need to check if docs are up to date,\n // we always want to retrigger a new build\n return 'cached';\n }\n\n // Used by transformer to modify the request to assets (CSS, Image) from inside the HTML.\n async getBaseUrl(\n oldBaseUrl: string,\n _entityId: CompoundEntityRef,\n path: string,\n ): Promise<string> {\n const apiOrigin = await this.getApiOrigin();\n return new URL(oldBaseUrl, `${apiOrigin}/${path}`).toString();\n }\n}\n\nclass TechDocsDevApi implements TechDocsApi {\n public configApi: Config;\n public discoveryApi: DiscoveryApi;\n public identityApi: IdentityApi;\n\n constructor({\n configApi,\n discoveryApi,\n identityApi,\n }: {\n configApi: Config;\n discoveryApi: DiscoveryApi;\n identityApi: IdentityApi;\n }) {\n this.configApi = configApi;\n this.discoveryApi = discoveryApi;\n this.identityApi = identityApi;\n }\n\n async getCookie(): Promise<{ expiresAt: string }> {\n const tenMinutesFromNow = new Date(Date.now() + 10 * 60 * 1000);\n return { expiresAt: tenMinutesFromNow.toISOString() };\n }\n\n async getApiOrigin() {\n return await this.discoveryApi.getBaseUrl('techdocs');\n }\n\n async getEntityMetadata(_entityId: any) {\n return {\n apiVersion: 'backstage.io/v1alpha1',\n kind: 'Component',\n metadata: {\n name: 'local',\n },\n spec: {\n owner: 'test',\n lifecycle: 'experimental',\n },\n };\n }\n\n async getTechDocsMetadata(_entityId: CompoundEntityRef) {\n return {\n site_name: 'Live preview environment',\n site_description: '',\n };\n }\n}\n\nexport const apis: AnyApiFactory[] = [\n createApiFactory({\n api: techdocsStorageApiRef,\n deps: {\n configApi: configApiRef,\n discoveryApi: discoveryApiRef,\n identityApi: identityApiRef,\n },\n factory: ({ configApi, discoveryApi, identityApi }) =>\n new TechDocsDevStorageApi({\n configApi,\n discoveryApi,\n identityApi,\n }),\n }),\n createApiFactory({\n api: techdocsApiRef,\n deps: {\n configApi: configApiRef,\n discoveryApi: discoveryApiRef,\n identityApi: identityApiRef,\n },\n factory: ({ configApi, discoveryApi, identityApi }) =>\n new TechDocsDevApi({\n configApi,\n discoveryApi,\n identityApi,\n }),\n }),\n createApiFactory({\n api: scmIntegrationsApiRef,\n deps: { configApi: configApiRef },\n factory: ({ configApi }) => ScmIntegrationsApi.fromConfig(configApi),\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 { defaultConfigLoader } from '@backstage/core-app-api';\n\nconst PRODUCTION_CONFIG = {\n backend: {\n baseUrl: 'http://localhost:3000',\n },\n techdocs: {\n builder: 'external',\n },\n};\n\nconst DEVELOPMENT_CONFIG = {\n backend: {\n baseUrl: 'http://localhost:7007',\n },\n techdocs: {\n builder: 'external',\n },\n};\n\nasync function isProductionServe() {\n const res = await fetch('/.detect');\n if (!res.ok) {\n return false;\n }\n const text = await res.text();\n return text.trim() === 'techdocs-cli-server';\n}\n\nexport async function configLoader() {\n const defaultConfigs = await defaultConfigLoader();\n const isProduction = await isProductionServe();\n\n return [\n ...defaultConfigs,\n {\n context: 'detected',\n data: isProduction ? PRODUCTION_CONFIG : DEVELOPMENT_CONFIG,\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 { makeStyles } from '@material-ui/core/styles';\n\nconst useStyles = makeStyles({\n svg: {\n width: 'auto',\n height: 30,\n },\n path: {\n fill: '#7df3e1',\n },\n});\nconst LogoFull = () => {\n const classes = useStyles();\n\n return (\n <svg\n className={classes.svg}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 2079.95 456.05\"\n >\n <path\n className={classes.path}\n d=\"M302.9,180a80.62,80.62,0,0,0,13.44-10.37c.8-.77,1.55-1.54,2.31-2.31a81.89,81.89,0,0,0,7.92-9.37,62.37,62.37,0,0,0,6.27-10.77,48.6,48.6,0,0,0,4.36-16.4c1.49-19.39-10-38.67-35.62-54.22L198.42,14,78.16,129.22l-78.29,75,108.6,65.9a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.8,66.42-25.69,19.16-18.36,25.52-42.12,13.7-61.87a49.69,49.69,0,0,0-6.8-8.87,89.78,89.78,0,0,0,19.28,2.15H259a85.09,85.09,0,0,0,31-5.79A80.88,80.88,0,0,0,302.9,180Zm-100.59,59.8c-19.32,18.51-50.4,21.24-75.7,5.9l-75.13-45.6,67.44-64.65,76.42,46.39C222.88,198.57,221.36,221.6,202.31,239.84Zm8.94-82.21L140.6,114.74,205,53l69.37,42.11c25.94,15.73,29.31,37.05,10.55,55A60.71,60.71,0,0,1,211.25,157.63Zm29.86,190c-19.57,18.75-46.17,29.08-74.88,29.08a123.84,123.84,0,0,1-64.11-18.19L-.13,296.51v24.67l108.6,65.91a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.81,66.42-25.69,12.88-12.34,20-27.13,19.68-41.49v-1.79A87.85,87.85,0,0,1,241.11,347.67Zm0-39c-19.57,18.76-46.17,29.09-74.88,29.09a123.84,123.84,0,0,1-64.11-18.19L-.13,257.52V282.2l108.6,65.91a111.59,111.59,0,0,0,57.76,16.41c24.92,0,48.8-8.8,66.42-25.68,12.88-12.35,20-27.13,19.68-41.5v-1.79A86.86,86.86,0,0,1,241.11,308.68Zm0-39c-19.57,18.76-46.17,29.09-74.88,29.09a123.84,123.84,0,0,1-64.11-18.19L-.13,218.54v24.68l108.6,65.91a111.59,111.59,0,0,0,57.76,16.41c24.92,0,48.8-8.8,66.42-25.69,12.88-12.34,20-27.12,19.68-41.49v-1.82A87.14,87.14,0,0,1,241.11,269.7Zm83.69,25.74a94.16,94.16,0,0,1-60.19,25.86h0V348a81.6,81.6,0,0,0,51.73-22.37c14-13.38,21.15-28.11,21-42.64v-2.2A95.14,95.14,0,0,1,324.8,295.44Zm-83.69,91.21c-19.57,18.75-46.17,29.09-74.88,29.09a123.76,123.76,0,0,1-64.11-18.2L-.13,335.49v24.67l108.6,65.91a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.81,66.42-25.69,12.88-12.34,20-27.13,19.68-41.49v-1.79A87.35,87.35,0,0,1,241.11,386.65Zm85.75-210.21c-.68.69-1.35,1.38-2.06,2.05a99.19,99.19,0,0,1-22.23,15.69,94.53,94.53,0,0,1-26.24,8.71,97.84,97.84,0,0,1-14.16,1.57c.5,1.61.9,3.25,1.25,4.9a52.7,52.7,0,0,1,1.13,12V231h.05A84.48,84.48,0,0,0,290,225.47a80.83,80.83,0,0,0,26.38-16.82c.81-.77,1.51-1.56,2.27-2.34a82,82,0,0,0,7.92-9.38,62.85,62.85,0,0,0,6.29-10.78,48.5,48.5,0,0,0,4.32-16.44c.09-1.23.2-2.47.19-3.7v-2c-.72,1-1.48,2.06-2.26,3.09A98,98,0,0,1,326.86,176.44Zm0,77.92c-.68.7-1.3,1.41-2,2.1a94.09,94.09,0,0,1-60.19,25.85h0V309h0a81.65,81.65,0,0,0,51.73-22.37,73.51,73.51,0,0,0,16.48-22.49,48.56,48.56,0,0,0,4.32-16.44c.09-1.24.2-2.48.19-3.71v-2.2c-.74,1.08-1.47,2.16-2.27,3.22A95.81,95.81,0,0,1,326.82,254.36Zm0-39c-.68.7-1.3,1.41-2,2.1a92.22,92.22,0,0,1-10.62,8.65,93.53,93.53,0,0,1-11.63,7,95.63,95.63,0,0,1-37.94,10.18h-.05l0,26.67h0a81.63,81.63,0,0,0,51.73-22.37c.81-.77,1.51-1.56,2.27-2.34a82,82,0,0,0,7.92-9.38,63.16,63.16,0,0,0,6.29-10.77,48.55,48.55,0,0,0,4.32-16.45c.09-1.23.2-2.47.19-3.7v-2.2c-.74,1.08-1.47,2.16-2.27,3.22A98.19,98.19,0,0,1,326.82,215.38Zm241-88.84q7.94,0,17.09.17t18.12,1a139.3,139.3,0,0,1,16.74,2.57,42.78,42.78,0,0,1,13.3,5.14,64.27,64.27,0,0,1,20.54,19.89Q662,168,662,186.54q0,19.54-9.49,33.78t-27.1,21.09v.68q22.78,4.82,34.87,20.58t12.08,38.4a72.62,72.62,0,0,1-4.83,26.06,65.29,65.29,0,0,1-14.33,22.46,71.57,71.57,0,0,1-23.47,15.78q-14,6-32.28,6H478.38V126.54Zm9,105.27q28,0,40.21-9.78t12.26-29.31q0-13-4.14-20.58a29.47,29.47,0,0,0-11.4-11.66A45,45,0,0,0,597,155.17a161.2,161.2,0,0,0-20.19-1.2h-65.6v77.84Zm16.57,112.13q21.74,0,34-11.66T639.59,300q0-12-4.48-19.88a34.85,34.85,0,0,0-11.91-12.52,50.14,50.14,0,0,0-17.09-6.52,105,105,0,0,0-20-1.88H511.17v84.7Zm274.79,26.74q-7.61,4.45-21.06,4.46-11.4,0-18.12-6.34t-6.74-20.75a70.17,70.17,0,0,1-28.13,20.75,97.87,97.87,0,0,1-57.65,3.6,53.51,53.51,0,0,1-18.82-8.58A41.19,41.19,0,0,1,705,348.56q-4.65-9.42-4.66-22.8,0-15.09,5.18-24.69a44.92,44.92,0,0,1,13.64-15.6,62.63,62.63,0,0,1,19.33-9.09q10.88-3.08,22.27-5.14,12.08-2.4,23-3.6a128,128,0,0,0,19.16-3.43c5.53-1.48,9.89-3.65,13.12-6.51s4.83-7,4.83-12.52q0-9.6-3.62-15.43a24.94,24.94,0,0,0-9.32-8.92,38.38,38.38,0,0,0-12.78-4.11,96.54,96.54,0,0,0-14-1q-18.63,0-31.07,7T736.6,249.29H707.26q.69-16.46,6.9-27.77a52.21,52.21,0,0,1,16.57-18.35,70,70,0,0,1,23.65-10.11A125.51,125.51,0,0,1,782.86,190a168.63,168.63,0,0,1,24,1.72,63.26,63.26,0,0,1,21.58,7A41.23,41.23,0,0,1,844,213.59q5.87,9.57,5.87,25v91q0,10.26,1.21,15.05t8.11,4.79a35.57,35.57,0,0,0,9-1.37Zm-47.64-90.87c-3.69,2.74-8.52,4.72-14.5,6s-12.26,2.27-18.82,3.07-13.17,1.71-19.85,2.73a73.7,73.7,0,0,0-18,4.94,32.62,32.62,0,0,0-12.94,9.73q-5,6.32-5,17.23a23.31,23.31,0,0,0,2.94,12.11,24.11,24.11,0,0,0,7.59,8,32,32,0,0,0,10.88,4.44,60.94,60.94,0,0,0,13.11,1.36q14.5,0,24.86-3.92a52.49,52.49,0,0,0,16.91-9.9,39.1,39.1,0,0,0,9.67-13,32.53,32.53,0,0,0,3.11-13.14ZM1002.07,225q-11.05-9.25-29.69-9.26-15.89,0-26.58,5.83A47.29,47.29,0,0,0,928.71,237a64.66,64.66,0,0,0-9.15,22.12A119.83,119.83,0,0,0,916.8,285a98.22,98.22,0,0,0,2.93,24,64.18,64.18,0,0,0,9.15,20.74,46.2,46.2,0,0,0,16.23,14.58q10,5.49,23.82,5.48,21.75,0,34-11.31t15-31.89h30q-4.83,32.91-24.68,50.75t-54,17.83q-20.37,0-36.07-6.52A69.86,69.86,0,0,1,907,350.11a79.92,79.92,0,0,1-15.88-28.63A118.64,118.64,0,0,1,885.73,285a129.41,129.41,0,0,1,5.18-37.21,85.63,85.63,0,0,1,15.71-30.17A73.46,73.46,0,0,1,933,197.35Q948.91,190,970,190a108.54,108.54,0,0,1,28.48,3.6,69.59,69.59,0,0,1,23.48,11.15,61,61,0,0,1,16.74,19q6.55,11.49,8.29,27.26h-30.38Q1013.11,234.21,1002.07,225Zm109.77-98.41v145l81.47-77.49h39.36l-70.77,64.46,75.95,112.82h-37.29l-61.1-92.59-27.62,25.38v67.21H1082.5V126.54Zm170.54,205.22a31.07,31.07,0,0,0,10.87,10.63,49,49,0,0,0,15.19,5.66,87.06,87.06,0,0,0,17.44,1.71,109.18,109.18,0,0,0,14.5-1,53.22,53.22,0,0,0,14-3.78,26.27,26.27,0,0,0,10.53-8q4.14-5.32,4.14-13.55,0-11.31-8.63-17.14a73.69,73.69,0,0,0-21.58-9.43q-12.94-3.6-28.13-6.52a146,146,0,0,1-28.14-8.23A58.16,58.16,0,0,1,1261,267.13q-8.64-9.6-8.63-26.75,0-13.38,6-23a49.26,49.26,0,0,1,15.53-15.61,71.76,71.76,0,0,1,21.4-8.91A99.41,99.41,0,0,1,1319,190a141.31,141.31,0,0,1,28,2.58,64.85,64.85,0,0,1,22.62,8.91,46.16,46.16,0,0,1,15.7,17.15q5.87,10.8,6.91,26.91h-29.35q-.69-8.57-4.48-14.23a29.36,29.36,0,0,0-9.67-9.08,44.16,44.16,0,0,0-12.94-5,67.68,67.68,0,0,0-14.33-1.54,87.29,87.29,0,0,0-13.29,1,45.28,45.28,0,0,0-12.26,3.6,24.49,24.49,0,0,0-9,6.86q-3.46,4.29-3.46,11.14a16.32,16.32,0,0,0,5.36,12.52,42.75,42.75,0,0,0,13.63,8.23,120,120,0,0,0,18.64,5.48q10.37,2.24,20.72,4.63,11,2.4,21.57,5.83A70.74,70.74,0,0,1,1382,284.1a44.55,44.55,0,0,1,13.12,14.23q5,8.58,5,21.26,0,16.13-6.73,26.75a52.5,52.5,0,0,1-17.61,17.14,73.89,73.89,0,0,1-24.51,9.09,146.3,146.3,0,0,1-27.1,2.57,126.24,126.24,0,0,1-28.31-3.09A69.56,69.56,0,0,1,1272,361.94a51.74,51.74,0,0,1-16.57-18.52q-6.21-11.49-6.9-27.95h29.34A32.65,32.65,0,0,0,1282.38,331.76Zm226.46-137.67v25.72h-35.56V329.88a31.37,31.37,0,0,0,.87,8.23,8.42,8.42,0,0,0,3.28,4.8,14.61,14.61,0,0,0,6.73,2.23,99.19,99.19,0,0,0,11.22.51h13.46v25.72H1486.4a105.8,105.8,0,0,1-19.5-1.55,28.65,28.65,0,0,1-13.12-5.65,24.09,24.09,0,0,1-7.42-11.66q-2.43-7.54-2.42-19.89V219.81h-30.38V194.09h30.38V140.94h29.34v53.15ZM1699.4,370.68q-7.61,4.45-21.06,4.46-11.4,0-18.12-6.34t-6.74-20.75a70.17,70.17,0,0,1-28.13,20.75,97.87,97.87,0,0,1-57.65,3.6,53.51,53.51,0,0,1-18.82-8.58,41.19,41.19,0,0,1-12.6-15.26q-4.65-9.42-4.66-22.8,0-15.09,5.18-24.69a44.92,44.92,0,0,1,13.64-15.6,62.63,62.63,0,0,1,19.33-9.09q10.88-3.08,22.27-5.14,12.07-2.4,23-3.6a128,128,0,0,0,19.16-3.43c5.53-1.48,9.89-3.65,13.12-6.51s4.83-7,4.83-12.52q0-9.6-3.62-15.43a24.94,24.94,0,0,0-9.32-8.92,38.38,38.38,0,0,0-12.78-4.11,96.54,96.54,0,0,0-14-1q-18.63,0-31.07,7t-13.46,26.57h-29.34q.67-16.46,6.9-27.77A52.21,52.21,0,0,1,1562,203.17a70,70,0,0,1,23.65-10.11,125.51,125.51,0,0,1,28.48-3.09,168.63,168.63,0,0,1,24,1.72,63.26,63.26,0,0,1,21.58,7,41.23,41.23,0,0,1,15.53,14.89q5.87,9.57,5.87,25v91q0,10.26,1.21,15.05t8.11,4.79a35.57,35.57,0,0,0,9-1.37Zm-47.64-90.87c-3.69,2.74-8.52,4.72-14.5,6s-12.26,2.27-18.82,3.07-13.17,1.71-19.85,2.73a73.7,73.7,0,0,0-17.95,4.94,32.62,32.62,0,0,0-12.94,9.73q-5,6.32-5,17.23a23.31,23.31,0,0,0,2.94,12.11,24.11,24.11,0,0,0,7.59,8,32,32,0,0,0,10.88,4.44,60.94,60.94,0,0,0,13.11,1.36q14.51,0,24.86-3.92a52.49,52.49,0,0,0,16.91-9.9,39.1,39.1,0,0,0,9.67-13,32.53,32.53,0,0,0,3.11-13.14Zm208.85,141.62q-20,21.6-62.83,21.6a122.11,122.11,0,0,1-25.37-2.74,78,78,0,0,1-23.48-8.92,54.41,54.41,0,0,1-17.43-16.11q-6.91-10-7.6-24.35h29.35a21.47,21.47,0,0,0,5,13.38,36.67,36.67,0,0,0,11.4,8.91,55.52,55.52,0,0,0,14.67,5,79.51,79.51,0,0,0,15.19,1.55q14.49,0,24.51-5A46,46,0,0,0,1840.59,401a56.53,56.53,0,0,0,9.49-21.09,117.46,117.46,0,0,0,2.94-27.09V341.19h-.7q-7.59,16.46-23,24.18a71.8,71.8,0,0,1-32.63,7.71q-20,0-34.86-7.2A72.88,72.88,0,0,1,1737,346.51a82.13,82.13,0,0,1-15-28.46,116.62,116.62,0,0,1-5-34.47,133.92,133.92,0,0,1,4.14-32.4A88.17,88.17,0,0,1,1735,221a75.49,75.49,0,0,1,25.55-22.29q15.87-8.75,39-8.75a66.21,66.21,0,0,1,31.07,7.38,52.13,52.13,0,0,1,22.09,22.11h.35V194.09h27.61V356.28Q1880.63,399.83,1860.61,421.43Zm-37.46-79.72a47.94,47.94,0,0,0,16.4-15.78,71.89,71.89,0,0,0,9.15-22.11,106.77,106.77,0,0,0,2.93-24.69,96.71,96.71,0,0,0-2.76-23,64,64,0,0,0-8.8-20.4,45.76,45.76,0,0,0-15.71-14.57q-9.66-5.49-23.47-5.49-14.16,0-24.17,5.32a46.77,46.77,0,0,0-16.4,14.23,60.14,60.14,0,0,0-9.32,20.57,99.69,99.69,0,0,0-2.93,24.35,120.63,120.63,0,0,0,2.42,24,67.5,67.5,0,0,0,8.28,21.77,46.37,46.37,0,0,0,15.54,15.78q9.66,6,24.16,6T1823.15,341.71Zm228,18.34q-20,15.09-50.41,15.09-21.4,0-37.11-6.86a73.16,73.16,0,0,1-26.41-19.2,81.52,81.52,0,0,1-16-29.49,141.12,141.12,0,0,1-6-37.38,106.1,106.1,0,0,1,6.21-37A88.56,88.56,0,0,1,1938.8,216a79.09,79.09,0,0,1,26.58-19.2A81.66,81.66,0,0,1,1999,190q23.82,0,39.53,9.78a78,78,0,0,1,25.2,24.86,98.18,98.18,0,0,1,13.12,32.91,140.6,140.6,0,0,1,2.93,34h-133.6a70,70,0,0,0,2.76,22.12,49.9,49.9,0,0,0,10,18.51A49.1,49.1,0,0,0,1976.6,345q10.7,4.82,25.2,4.8,18.65,0,30.55-8.57t15.71-26.06h29Q2071.18,345,2051.17,360.05Zm-7.08-113.84a50,50,0,0,0-10.7-16,53.1,53.1,0,0,0-56.62-10.63,47.48,47.48,0,0,0-15.71,10.81,51.69,51.69,0,0,0-10.35,15.94,60.18,60.18,0,0,0-4.49,19.37h102.53A59.47,59.47,0,0,0,2044.09,246.21ZM302.9,180a80.62,80.62,0,0,0,13.44-10.37c.8-.77,1.55-1.54,2.31-2.31a81.89,81.89,0,0,0,7.92-9.37,62.37,62.37,0,0,0,6.27-10.77,48.6,48.6,0,0,0,4.36-16.4c1.49-19.39-10-38.67-35.62-54.22L198.42,14,78.16,129.22l-78.29,75,108.6,65.9a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.8,66.42-25.69,19.16-18.36,25.52-42.12,13.7-61.87a49.69,49.69,0,0,0-6.8-8.87,89.78,89.78,0,0,0,19.28,2.15H259a85.09,85.09,0,0,0,31-5.79A80.88,80.88,0,0,0,302.9,180Zm-100.59,59.8c-19.32,18.51-50.4,21.24-75.7,5.9l-75.13-45.6,67.44-64.65,76.42,46.39C222.88,198.57,221.36,221.6,202.31,239.84Zm8.94-82.21L140.6,114.74,205,53l69.37,42.11c25.94,15.73,29.31,37.05,10.55,55A60.71,60.71,0,0,1,211.25,157.63Zm29.86,190c-19.57,18.75-46.17,29.08-74.88,29.08a123.84,123.84,0,0,1-64.11-18.19L-.13,296.51v24.67l108.6,65.91a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.81,66.42-25.69,12.88-12.34,20-27.13,19.68-41.49v-1.79A87.85,87.85,0,0,1,241.11,347.67Zm0-39c-19.57,18.76-46.17,29.09-74.88,29.09a123.84,123.84,0,0,1-64.11-18.19L-.13,257.52V282.2l108.6,65.91a111.59,111.59,0,0,0,57.76,16.41c24.92,0,48.8-8.8,66.42-25.68,12.88-12.35,20-27.13,19.68-41.5v-1.79A86.86,86.86,0,0,1,241.11,308.68Zm0-39c-19.57,18.76-46.17,29.09-74.88,29.09a123.84,123.84,0,0,1-64.11-18.19L-.13,218.54v24.68l108.6,65.91a111.59,111.59,0,0,0,57.76,16.41c24.92,0,48.8-8.8,66.42-25.69,12.88-12.34,20-27.12,19.68-41.49v-1.82A87.14,87.14,0,0,1,241.11,269.7Zm83.69,25.74a94.16,94.16,0,0,1-60.19,25.86h0V348a81.6,81.6,0,0,0,51.73-22.37c14-13.38,21.15-28.11,21-42.64v-2.2A95.14,95.14,0,0,1,324.8,295.44Zm-83.69,91.21c-19.57,18.75-46.17,29.09-74.88,29.09a123.76,123.76,0,0,1-64.11-18.2L-.13,335.49v24.67l108.6,65.91a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.81,66.42-25.69,12.88-12.34,20-27.13,19.68-41.49v-1.79A87.35,87.35,0,0,1,241.11,386.65Zm85.75-210.21c-.68.69-1.35,1.38-2.06,2.05a99.19,99.19,0,0,1-22.23,15.69,94.53,94.53,0,0,1-26.24,8.71,97.84,97.84,0,0,1-14.16,1.57c.5,1.61.9,3.25,1.25,4.9a52.7,52.7,0,0,1,1.13,12V231h.05A84.48,84.48,0,0,0,290,225.47a80.83,80.83,0,0,0,26.38-16.82c.81-.77,1.51-1.56,2.27-2.34a82,82,0,0,0,7.92-9.38,62.85,62.85,0,0,0,6.29-10.78,48.5,48.5,0,0,0,4.32-16.44c.09-1.23.2-2.47.19-3.7v-2c-.72,1-1.48,2.06-2.26,3.09A98,98,0,0,1,326.86,176.44Zm0,77.92c-.68.7-1.3,1.41-2,2.1a94.09,94.09,0,0,1-60.19,25.85h0V309h0a81.65,81.65,0,0,0,51.73-22.37,73.51,73.51,0,0,0,16.48-22.49,48.56,48.56,0,0,0,4.32-16.44c.09-1.24.2-2.48.19-3.71v-2.2c-.74,1.08-1.47,2.16-2.27,3.22A95.81,95.81,0,0,1,326.82,254.36Zm0-39c-.68.7-1.3,1.41-2,2.1a92.22,92.22,0,0,1-10.62,8.65,93.53,93.53,0,0,1-11.63,7,95.63,95.63,0,0,1-37.94,10.18h-.05l0,26.67h0a81.63,81.63,0,0,0,51.73-22.37c.81-.77,1.51-1.56,2.27-2.34a82,82,0,0,0,7.92-9.38,63.16,63.16,0,0,0,6.29-10.77,48.55,48.55,0,0,0,4.32-16.45c.09-1.23.2-2.47.19-3.7v-2.2c-.74,1.08-1.47,2.16-2.27,3.22A98.19,98.19,0,0,1,326.82,215.38Z\"\n />\n </svg>\n );\n};\n\nexport default LogoFull;\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 { makeStyles } from '@material-ui/core/styles';\n\nconst useStyles = makeStyles({\n svg: {\n width: 'auto',\n height: 28,\n },\n path: {\n fill: '#7df3e1',\n },\n});\n\nconst LogoIcon = () => {\n const classes = useStyles();\n\n return (\n <svg\n className={classes.svg}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 337.46 428.5\"\n >\n <path\n className={classes.path}\n d=\"M303,166.05a80.69,80.69,0,0,0,13.45-10.37c.79-.77,1.55-1.53,2.3-2.3a83.12,83.12,0,0,0,7.93-9.38A63.69,63.69,0,0,0,333,133.23a48.58,48.58,0,0,0,4.35-16.4c1.49-19.39-10-38.67-35.62-54.22L198.56,0,78.3,115.23,0,190.25l108.6,65.91a111.59,111.59,0,0,0,57.76,16.41c24.92,0,48.8-8.8,66.42-25.69,19.16-18.36,25.52-42.12,13.7-61.87a49.22,49.22,0,0,0-6.8-8.87A89.17,89.17,0,0,0,259,178.29h.15a85.08,85.08,0,0,0,31-5.79A80.88,80.88,0,0,0,303,166.05ZM202.45,225.86c-19.32,18.51-50.4,21.23-75.7,5.9L51.61,186.15l67.45-64.64,76.41,46.38C223,184.58,221.49,207.61,202.45,225.86Zm8.93-82.22-70.65-42.89L205.14,39,274.51,81.1c25.94,15.72,29.31,37,10.55,55A60.69,60.69,0,0,1,211.38,143.64Zm29.86,190c-19.57,18.75-46.17,29.09-74.88,29.09a123.73,123.73,0,0,1-64.1-18.2L0,282.52v24.67L108.6,373.1a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.81,66.42-25.69,12.88-12.34,20-27.13,19.68-41.49v-1.79A87.27,87.27,0,0,1,241.24,333.68Zm0-39c-19.57,18.75-46.17,29.08-74.88,29.08a123.81,123.81,0,0,1-64.1-18.19L0,243.53v24.68l108.6,65.91a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.81,66.42-25.69,12.88-12.34,20-27.13,19.68-41.5v-1.78A87.27,87.27,0,0,1,241.24,294.7Zm0-39c-19.57,18.76-46.17,29.09-74.88,29.09a123.81,123.81,0,0,1-64.1-18.19L0,204.55v24.68l108.6,65.91a111.59,111.59,0,0,0,57.76,16.41c24.92,0,48.8-8.8,66.42-25.68,12.88-12.35,20-27.13,19.68-41.5v-1.82A86.09,86.09,0,0,1,241.24,255.71Zm83.7,25.74a94.15,94.15,0,0,1-60.2,25.86h0V334a81.6,81.6,0,0,0,51.74-22.37c14-13.38,21.14-28.11,21-42.64v-2.19A94.92,94.92,0,0,1,324.94,281.45Zm-83.7,91.21c-19.57,18.76-46.17,29.09-74.88,29.09a123.73,123.73,0,0,1-64.1-18.2L0,321.5v24.68l108.6,65.9a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.8,66.42-25.69,12.88-12.34,20-27.13,19.68-41.49v-1.79A86.29,86.29,0,0,1,241.24,372.66ZM327,162.45c-.68.69-1.35,1.38-2.05,2.06a94.37,94.37,0,0,1-10.64,8.65,91.35,91.35,0,0,1-11.6,7,94.53,94.53,0,0,1-26.24,8.71,97.69,97.69,0,0,1-14.16,1.57c.5,1.61.9,3.25,1.25,4.9a53.27,53.27,0,0,1,1.14,12V217h.05a84.41,84.41,0,0,0,25.35-5.55,81,81,0,0,0,26.39-16.82c.8-.77,1.5-1.56,2.26-2.34a82.08,82.08,0,0,0,7.93-9.38A63.76,63.76,0,0,0,333,172.17a48.55,48.55,0,0,0,4.32-16.45c.09-1.23.2-2.47.19-3.7V150q-1.08,1.54-2.25,3.09A96.73,96.73,0,0,1,327,162.45Zm0,77.92c-.69.7-1.31,1.41-2,2.1a94.2,94.2,0,0,1-60.2,25.86h0l0,26.67h0a81.6,81.6,0,0,0,51.74-22.37A73.51,73.51,0,0,0,333,250.13a48.56,48.56,0,0,0,4.32-16.44c.09-1.24.2-2.47.19-3.71v-2.19c-.74,1.07-1.46,2.15-2.27,3.21A95.68,95.68,0,0,1,327,240.37Zm0-39c-.69.7-1.31,1.41-2,2.1a93.18,93.18,0,0,1-10.63,8.65,91.63,91.63,0,0,1-11.63,7,95.47,95.47,0,0,1-37.94,10.18h0V256h0a81.65,81.65,0,0,0,51.74-22.37c.8-.77,1.5-1.56,2.26-2.34a82.08,82.08,0,0,0,7.93-9.38A63.76,63.76,0,0,0,333,211.15a48.56,48.56,0,0,0,4.32-16.44c.09-1.24.2-2.48.19-3.71v-2.2c-.74,1.08-1.46,2.16-2.27,3.22A95.68,95.68,0,0,1,327,201.39Z\"\n />\n </svg>\n );\n};\n\nexport default LogoIcon;\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 */\n\nimport { createContext, ReactNode, useContext } from 'react';\nimport {\n createVersionedContext,\n createVersionedValueMap,\n} from '@backstage/version-bridge';\n\n/**\n * Types for the `SidebarContext`\n *\n * @public @deprecated\n * Use `SidebarOpenState` instead.\n */\nexport type SidebarContextType = {\n isOpen: boolean;\n setOpen: (open: boolean) => void;\n};\n\n/**\n * The open state of the sidebar.\n *\n * @public\n */\nexport type SidebarOpenState = {\n /**\n * Whether or not the sidebar is open and full-width. When `false`, the\n * sidebar is \"closed\" and typically only shows icons with no text.\n */\n isOpen: boolean;\n\n /**\n * A function to set whether or not the sidebar is open. Pass `true` to open\n * the sidebar. Pass `false` to close it.\n */\n setOpen: (open: boolean) => void;\n};\n\nconst defaultSidebarOpenStateContext = {\n isOpen: false,\n setOpen: () => {},\n};\n\n/**\n * Context whether the `Sidebar` is open\n *\n * @public @deprecated\n * Use `<SidebarOpenStateProvider>` + `useSidebarOpenState()` instead.\n */\nexport const LegacySidebarContext = createContext<SidebarContextType>(\n defaultSidebarOpenStateContext,\n);\n\nconst VersionedSidebarContext = createVersionedContext<{\n 1: SidebarOpenState;\n}>('sidebar-open-state-context');\n\n/**\n * Provides context for reading and updating sidebar state.\n *\n * @public\n */\nexport function SidebarOpenStateProvider(props: {\n children: ReactNode;\n value: SidebarOpenState;\n}) {\n const { children, value } = props;\n return (\n <LegacySidebarContext.Provider value={value}>\n <VersionedSidebarContext.Provider\n value={createVersionedValueMap({ 1: value })}\n >\n {children}\n </VersionedSidebarContext.Provider>\n </LegacySidebarContext.Provider>\n );\n}\n\n/**\n * Hook to read and update the sidebar's open state, which controls whether or\n * not the sidebar is open and full-width, or closed and only displaying icons.\n *\n * @public\n */\nexport const useSidebarOpenState = (): SidebarOpenState => {\n const versionedOpenStateContext = useContext(VersionedSidebarContext);\n const legacyOpenStateContext = useContext(LegacySidebarContext);\n\n // Invoked from outside a SidebarOpenStateProvider: check for the legacy\n // context's value, but otherwise return the default.\n if (versionedOpenStateContext === undefined) {\n return legacyOpenStateContext || defaultSidebarOpenStateContext;\n }\n\n const openStateContext = versionedOpenStateContext.atVersion(1);\n if (openStateContext === undefined) {\n throw new Error('No context found for version 1.');\n }\n\n return openStateContext;\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 { SetStateAction, Dispatch, createContext } from 'react';\n\n/**\n * Type of `MobileSidebarContext`\n *\n * @internal\n */\nexport type MobileSidebarContextType = {\n selectedMenuItemIndex: number;\n setSelectedMenuItemIndex: Dispatch<SetStateAction<number>>;\n};\n\n/**\n * Context on which `SidebarGroup` is currently selected\n *\n * @internal\n */\nexport const MobileSidebarContext = createContext<MobileSidebarContextType>({\n selectedMenuItemIndex: -1,\n setSelectedMenuItemIndex: () => {},\n});\n","/* eslint-disable @typescript-eslint/no-shadow */\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 BottomNavigationAction, {\n BottomNavigationActionProps,\n} from '@material-ui/core/BottomNavigationAction';\nimport { Theme, makeStyles } from '@material-ui/core/styles';\nimport { ReactNode, ChangeEvent, useContext } from 'react';\nimport { useLocation } from 'react-router-dom';\nimport { Link } from '../../components/Link/Link';\nimport { SidebarConfig, SidebarConfigContext } from './config';\nimport { MobileSidebarContext } from './MobileSidebarContext';\nimport { useSidebarPinState } from './SidebarPinStateContext';\n\n/**\n * Props for the `SidebarGroup`\n *\n * @public\n */\nexport interface SidebarGroupProps extends BottomNavigationActionProps {\n /**\n * If the `SidebarGroup` should be a `Link`, `to` should be a pathname to that location\n */\n to?: string;\n /**\n * If the `SidebarGroup`s should be in a different order than in the normal `Sidebar`, you can provide\n * each `SidebarGroup` it's own priority to reorder them.\n */\n priority?: number;\n /**\n * React children\n */\n children?: ReactNode;\n}\n\nconst useStyles = makeStyles<Theme, { sidebarConfig: SidebarConfig }>(\n theme => ({\n root: {\n flexGrow: 0,\n margin: theme.spacing(0, 2),\n color: theme.palette.navigation.color,\n },\n\n selected: props => ({\n color: `${theme.palette.navigation.selectedColor}!important`,\n borderTop: `solid ${props.sidebarConfig.selectedIndicatorWidth}px ${theme.palette.navigation.indicator}`,\n marginTop: '-1px',\n }),\n\n label: {\n display: 'none',\n },\n }),\n);\n\n/**\n * Returns a Material UI `BottomNavigationAction`, which is aware of the current location & the selected item in the `BottomNavigation`,\n * such that it will highlight a `MobileSidebarGroup` either on location change or if the selected item changes.\n *\n * @param props `to`: pathname of link; `value`: index of the selected item\n * @internal\n */\nconst MobileSidebarGroup = (props: SidebarGroupProps) => {\n const { to, label, icon, value } = props;\n const { sidebarConfig } = useContext(SidebarConfigContext);\n const classes = useStyles({ sidebarConfig });\n const location = useLocation();\n const { selectedMenuItemIndex, setSelectedMenuItemIndex } =\n useContext(MobileSidebarContext);\n\n const onChange = (_: ChangeEvent<{}>, value: number) => {\n if (value === selectedMenuItemIndex) {\n setSelectedMenuItemIndex(-1);\n } else {\n setSelectedMenuItemIndex(value);\n }\n };\n\n const selected =\n (value === selectedMenuItemIndex && selectedMenuItemIndex >= 0) ||\n (!(value === selectedMenuItemIndex) &&\n !(selectedMenuItemIndex >= 0) &&\n to === location.pathname);\n\n return (\n // Material UI issue: https://github.com/mui-org/material-ui/issues/27820\n <BottomNavigationAction\n aria-label={label}\n label={label}\n icon={icon}\n component={Link as any}\n to={(to ? to : location.pathname) as any}\n onChange={onChange}\n value={value}\n selected={selected}\n classes={classes}\n />\n );\n};\n\n/**\n * Groups items of the `Sidebar` together.\n *\n * @remarks\n * On bigger screens, this won't have any effect at the moment.\n * On small screens, it will add an action to the bottom navigation - either triggering an overlay menu or acting as a link\n *\n * @public\n */\nexport const SidebarGroup = (props: SidebarGroupProps) => {\n const { children, to, label, icon, value } = props;\n const { isMobile } = useSidebarPinState();\n\n return isMobile ? (\n <MobileSidebarGroup to={to} label={label} icon={icon} value={value} />\n ) : (\n <>{children}</>\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 { useElementFilter } from '@backstage/core-plugin-api';\nimport BottomNavigation from '@material-ui/core/BottomNavigation';\nimport Box from '@material-ui/core/Box';\nimport IconButton from '@material-ui/core/IconButton';\nimport { Theme, makeStyles } from '@material-ui/core/styles';\nimport Drawer from '@material-ui/core/Drawer';\nimport Typography from '@material-ui/core/Typography';\nimport CloseIcon from '@material-ui/icons/Close';\nimport MenuIcon from '@material-ui/icons/Menu';\nimport { orderBy } from 'lodash';\nimport {\n useEffect,\n useState,\n useContext,\n ReactNode,\n ReactElement,\n createElement,\n} from 'react';\nimport { useLocation } from 'react-router-dom';\nimport { SidebarOpenStateProvider } from './SidebarOpenStateContext';\nimport { SidebarGroup } from './SidebarGroup';\nimport { SidebarConfigContext, SidebarConfig } from './config';\nimport { MobileSidebarContext } from './MobileSidebarContext';\n\n/**\n * Props of MobileSidebar\n *\n * @public\n */\nexport type MobileSidebarProps = {\n children?: ReactNode;\n};\n\n/**\n * @internal\n */\ntype OverlayMenuProps = {\n label?: string;\n onClose: () => void;\n open: boolean;\n children?: ReactNode;\n};\n\nconst useStyles = makeStyles<Theme, { sidebarConfig: SidebarConfig }>(\n theme => ({\n root: {\n position: 'fixed',\n backgroundColor: theme.palette.navigation.background,\n color: theme.palette.navigation.color,\n bottom: 0,\n left: 0,\n right: 0,\n zIndex: theme.zIndex.snackbar,\n // SidebarDivider color\n borderTop: '1px solid #383838',\n '@media print': {\n display: 'none',\n },\n },\n\n overlay: props => ({\n background: theme.palette.navigation.background,\n width: '100%',\n bottom: `${props.sidebarConfig.mobileSidebarHeight}px`,\n height: `calc(100% - ${props.sidebarConfig.mobileSidebarHeight}px)`,\n flex: '0 1 auto',\n overflow: 'auto',\n }),\n\n overlayHeader: {\n display: 'flex',\n color: theme.palette.navigation.color,\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: theme.spacing(2, 3),\n },\n\n overlayHeaderClose: {\n color: theme.palette.navigation.color,\n },\n\n marginMobileSidebar: props => ({\n marginBottom: `${props.sidebarConfig.mobileSidebarHeight}px`,\n }),\n }),\n);\n\nconst sortSidebarGroupsForPriority = (children: ReactElement[]) =>\n orderBy(\n children,\n ({ props: { priority } }) => (Number.isInteger(priority) ? priority : -1),\n 'desc',\n );\n\nconst sidebarGroupType = createElement(SidebarGroup).type;\n\nconst OverlayMenu = ({\n children,\n label = 'Menu',\n open,\n onClose,\n}: OverlayMenuProps) => {\n const { sidebarConfig } = useContext(SidebarConfigContext);\n const classes = useStyles({ sidebarConfig });\n\n return (\n <Drawer\n anchor=\"bottom\"\n open={open}\n onClose={onClose}\n ModalProps={{\n BackdropProps: { classes: { root: classes.marginMobileSidebar } },\n }}\n classes={{\n root: classes.marginMobileSidebar,\n paperAnchorBottom: classes.overlay,\n }}\n >\n <Box className={classes.overlayHeader}>\n <Typography variant=\"h3\">{label}</Typography>\n <IconButton\n onClick={onClose}\n classes={{ root: classes.overlayHeaderClose }}\n >\n <CloseIcon />\n </IconButton>\n </Box>\n <Box component=\"nav\">{children}</Box>\n </Drawer>\n );\n};\n\n/**\n * A navigation component for mobile screens, which sticks to the bottom.\n *\n * @remarks\n * It alternates the normal sidebar by grouping the `SidebarItems` based on provided `SidebarGroup`s\n * either rendering them as a link or an overlay menu.\n * If no `SidebarGroup`s are provided the sidebar content is wrapped in an default overlay menu.\n *\n * @public\n */\nexport const MobileSidebar = (props: MobileSidebarProps) => {\n const { sidebarConfig } = useContext(SidebarConfigContext);\n const { children } = props;\n const classes = useStyles({ sidebarConfig });\n const location = useLocation();\n const [selectedMenuItemIndex, setSelectedMenuItemIndex] =\n useState<number>(-1);\n\n useEffect(() => {\n setSelectedMenuItemIndex(-1);\n }, [location.pathname]);\n\n // Filter children for SidebarGroups\n //\n // Directly comparing child.type with SidebarSubmenu will not work with in\n // combination with react-hot-loader\n //\n // https://github.com/gaearon/react-hot-loader/issues/304#issuecomment-456569720\n let sidebarGroups = useElementFilter(children, elements =>\n elements.getElements().filter(child => child.type === sidebarGroupType),\n );\n\n if (!children) {\n // If Sidebar has no children the MobileSidebar won't be rendered\n return null;\n } else if (!sidebarGroups.length) {\n // If Sidebar has no SidebarGroup as a children a default\n // SidebarGroup with the complete Sidebar content will be created\n sidebarGroups.push(\n <SidebarGroup key=\"default_menu\" icon={<MenuIcon />}>\n {children}\n </SidebarGroup>,\n );\n } else {\n // Sort SidebarGroups for the given Priority\n sidebarGroups = sortSidebarGroupsForPriority(sidebarGroups);\n }\n\n const shouldShowGroupChildren =\n selectedMenuItemIndex >= 0 &&\n !sidebarGroups[selectedMenuItemIndex].props.to;\n\n return (\n <SidebarOpenStateProvider value={{ isOpen: true, setOpen: () => {} }}>\n <MobileSidebarContext.Provider\n value={{ selectedMenuItemIndex, setSelectedMenuItemIndex }}\n >\n <OverlayMenu\n label={\n sidebarGroups[selectedMenuItemIndex] &&\n (sidebarGroups[selectedMenuItemIndex]!.props.label as string)\n }\n open={shouldShowGroupChildren}\n onClose={() => setSelectedMenuItemIndex(-1)}\n >\n {sidebarGroups[selectedMenuItemIndex] &&\n (sidebarGroups[selectedMenuItemIndex].props.children as ReactNode)}\n </OverlayMenu>\n <BottomNavigation\n className={classes.root}\n data-testid=\"mobile-sidebar-root\"\n component=\"nav\"\n >\n {sidebarGroups}\n </BottomNavigation>\n </MobileSidebarContext.Provider>\n </SidebarOpenStateProvider>\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, Theme } from '@material-ui/core/styles';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport classnames from 'classnames';\nimport { ReactNode, useContext, useRef, useState } from 'react';\n\nimport {\n makeSidebarConfig,\n makeSidebarSubmenuConfig,\n SidebarConfig,\n SidebarConfigContext,\n SidebarOptions,\n SubmenuConfig,\n SubmenuOptions,\n} from './config';\nimport { MobileSidebar } from './MobileSidebar';\nimport { useContent } from './Page';\nimport { SidebarOpenStateProvider } from './SidebarOpenStateContext';\nimport { useSidebarPinState } from './SidebarPinStateContext';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { coreComponentsTranslationRef } from '../../translation';\n\n/** @public */\nexport type SidebarClassKey = 'drawer' | 'drawerOpen';\nconst useStyles = makeStyles<Theme, { sidebarConfig: SidebarConfig }>(\n theme => ({\n root: {\n left: 0,\n top: 0,\n bottom: 0,\n zIndex: theme.zIndex.appBar,\n position: 'fixed',\n },\n drawer: {\n display: 'flex',\n flexFlow: 'column nowrap',\n alignItems: 'flex-start',\n left: 0,\n top: 0,\n bottom: 0,\n position: 'absolute',\n background: theme.palette.navigation.background,\n overflowX: 'hidden',\n msOverflowStyle: 'none',\n scrollbarWidth: 'none',\n transition: theme.transitions.create('width', {\n easing: theme.transitions.easing.sharp,\n duration: theme.transitions.duration.shortest,\n }),\n '& > *': {\n flexShrink: 0,\n },\n '&::-webkit-scrollbar': {\n display: 'none',\n },\n '@media print': {\n display: 'none',\n },\n },\n drawerWidth: props => ({\n width: props.sidebarConfig.drawerWidthClosed,\n }),\n drawerOpen: props => ({\n width: props.sidebarConfig.drawerWidthOpen,\n transition: theme.transitions.create('width', {\n easing: theme.transitions.easing.sharp,\n duration: theme.transitions.duration.shorter,\n }),\n }),\n visuallyHidden: {\n top: 0,\n position: 'absolute',\n zIndex: 1000,\n transform: 'translateY(-200%)',\n '&:focus': {\n transform: 'translateY(5px)',\n },\n },\n }),\n { name: 'BackstageSidebar' },\n);\n\nenum State {\n Closed,\n Idle,\n Open,\n}\n\n/** @public */\nexport type SidebarProps = {\n openDelayMs?: number;\n closeDelayMs?: number;\n sidebarOptions?: SidebarOptions;\n submenuOptions?: SubmenuOptions;\n disableExpandOnHover?: boolean;\n children?: ReactNode;\n};\n\nexport type DesktopSidebarProps = {\n openDelayMs?: number;\n closeDelayMs?: number;\n disableExpandOnHover?: boolean;\n children?: ReactNode;\n};\n\n/**\n * Places the Sidebar & wraps the children providing context weather the `Sidebar` is open or not.\n *\n * Handles & delays hover events for expanding the `Sidebar`\n *\n * @param props `disableExpandOnHover` disables the default hover behaviour;\n * `openDelayMs` & `closeDelayMs` set delay until sidebar will open/close on hover\n * @returns\n * @internal\n */\nconst DesktopSidebar = (props: DesktopSidebarProps) => {\n const { sidebarConfig } = useContext(SidebarConfigContext);\n const {\n openDelayMs = sidebarConfig.defaultOpenDelayMs,\n closeDelayMs = sidebarConfig.defaultCloseDelayMs,\n disableExpandOnHover,\n children,\n } = props;\n\n const classes = useStyles({ sidebarConfig });\n const isSmallScreen = useMediaQuery<Theme>(\n theme => theme.breakpoints.down('md'),\n { noSsr: true },\n );\n const [state, setState] = useState(State.Closed);\n const hoverTimerRef = useRef<number>();\n const { isPinned, toggleSidebarPinState } = useSidebarPinState();\n\n const handleOpen = () => {\n if (isPinned || disableExpandOnHover) {\n return;\n }\n if (hoverTimerRef.current) {\n clearTimeout(hoverTimerRef.current);\n hoverTimerRef.current = undefined;\n }\n if (state !== State.Open && !isSmallScreen) {\n hoverTimerRef.current = window.setTimeout(() => {\n hoverTimerRef.current = undefined;\n setState(State.Open);\n }, openDelayMs);\n\n setState(State.Idle);\n }\n };\n\n const handleClose = () => {\n if (isPinned || disableExpandOnHover) {\n return;\n }\n if (hoverTimerRef.current) {\n clearTimeout(hoverTimerRef.current);\n hoverTimerRef.current = undefined;\n }\n if (state === State.Idle) {\n setState(State.Closed);\n } else if (state === State.Open) {\n hoverTimerRef.current = window.setTimeout(() => {\n hoverTimerRef.current = undefined;\n setState(State.Closed);\n }, closeDelayMs);\n }\n };\n\n const isOpen = (state === State.Open && !isSmallScreen) || isPinned;\n\n /**\n * Close/Open Sidebar directly without delays. Also toggles `SidebarPinState` to avoid hidden content behind Sidebar.\n */\n const setOpen = (open: boolean) => {\n if (open) {\n setState(State.Open);\n toggleSidebarPinState();\n } else {\n setState(State.Closed);\n toggleSidebarPinState();\n }\n };\n\n return (\n <nav style={{}} aria-label=\"sidebar nav\">\n <A11ySkipSidebar />\n <SidebarOpenStateProvider value={{ isOpen, setOpen }}>\n <Box\n className={classes.root}\n data-testid=\"sidebar-root\"\n onMouseEnter={disableExpandOnHover ? () => {} : handleOpen}\n onFocus={disableExpandOnHover ? () => {} : handleOpen}\n onMouseLeave={disableExpandOnHover ? () => {} : handleClose}\n onBlur={disableExpandOnHover ? () => {} : handleClose}\n >\n <Box\n className={classnames(classes.drawer, classes.drawerWidth, {\n [classes.drawerOpen]: isOpen,\n })}\n >\n {children}\n </Box>\n </Box>\n </SidebarOpenStateProvider>\n </nav>\n );\n};\n\n/**\n * Passing children into the desktop or mobile sidebar depending on the context\n *\n * @public\n */\nexport const Sidebar = (props: SidebarProps) => {\n const sidebarConfig: SidebarConfig = makeSidebarConfig(\n props.sidebarOptions ?? {},\n );\n const submenuConfig: SubmenuConfig = makeSidebarSubmenuConfig(\n props.submenuOptions ?? {},\n );\n const { children, disableExpandOnHover, openDelayMs, closeDelayMs } = props;\n const { isMobile } = useSidebarPinState();\n\n return isMobile ? (\n <MobileSidebar>{children}</MobileSidebar>\n ) : (\n <SidebarConfigContext.Provider value={{ sidebarConfig, submenuConfig }}>\n <DesktopSidebar\n openDelayMs={openDelayMs}\n closeDelayMs={closeDelayMs}\n disableExpandOnHover={disableExpandOnHover}\n >\n {children}\n </DesktopSidebar>\n </SidebarConfigContext.Provider>\n );\n};\n\nfunction A11ySkipSidebar() {\n const { sidebarConfig } = useContext(SidebarConfigContext);\n const { focusContent, contentRef } = useContent();\n const classes = useStyles({ sidebarConfig });\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n\n if (!contentRef?.current) {\n return null;\n }\n return (\n <Button\n onClick={focusContent}\n variant=\"contained\"\n className={classnames(classes.visuallyHidden)}\n >\n {t('skipToContent')}\n </Button>\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 { makeStyles, Theme } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport classnames from 'classnames';\nimport { ReactNode, useContext, useEffect, useState } from 'react';\n\nimport {\n SidebarConfigContext,\n SidebarItemWithSubmenuContext,\n SubmenuConfig,\n} from './config';\nimport { useSidebarOpenState } from './SidebarOpenStateContext';\n\n/** @public */\nexport type SidebarSubmenuClassKey = 'root' | 'drawer' | 'drawerOpen' | 'title';\n\nconst useStyles = makeStyles<\n Theme,\n { submenuConfig: SubmenuConfig; left: number }\n>(\n theme => ({\n root: {\n zIndex: 1000,\n position: 'relative',\n overflow: 'visible',\n width: theme.spacing(7) + 1,\n },\n drawer: props => ({\n display: 'flex',\n flexFlow: 'column nowrap',\n alignItems: 'flex-start',\n position: 'fixed',\n opacity: 0,\n [theme.breakpoints.up('sm')]: {\n marginLeft: props.left,\n transition: theme.transitions.create(['margin-left', 'opacity'], {\n easing: theme.transitions.easing.sharp,\n duration: props.submenuConfig.defaultOpenDelayMs,\n }),\n },\n top: 0,\n bottom: 0,\n padding: 0,\n background: theme.palette.navigation.submenu?.background ?? '#404040',\n overflowX: 'hidden',\n msOverflowStyle: 'none',\n scrollbarWidth: 'none',\n cursor: 'default',\n width: props.submenuConfig.drawerWidthClosed,\n transitionDelay: `${props.submenuConfig.defaultOpenDelayMs}ms`,\n '& > *': {\n flexShrink: 0,\n },\n '&::-webkit-scrollbar': {\n display: 'none',\n },\n }),\n drawerOpen: props => ({\n marginLeft: props.left,\n opacity: 1,\n width: props.submenuConfig.drawerWidthOpen,\n [theme.breakpoints.down('xs')]: {\n width: '100%',\n position: 'relative',\n paddingLeft: theme.spacing(3),\n left: 0,\n top: 0,\n },\n }),\n title: {\n fontSize: theme.typography.h5.fontSize,\n fontWeight: theme.typography.fontWeightMedium,\n color: theme.palette.navigation.color,\n padding: theme.spacing(2.5),\n [theme.breakpoints.down('xs')]: {\n display: 'none',\n },\n },\n }),\n { name: 'BackstageSidebarSubmenu' },\n);\n\n/**\n * Holds a title for text Header of a sidebar submenu and children\n * components to be rendered inside SidebarSubmenu\n *\n * @public\n */\nexport type SidebarSubmenuProps = {\n title?: string;\n children: ReactNode;\n};\n\n/**\n * Used inside SidebarItem to display an expandable Submenu\n *\n * @public\n */\nexport const SidebarSubmenu = (props: SidebarSubmenuProps) => {\n const { isOpen } = useSidebarOpenState();\n const { sidebarConfig, submenuConfig } = useContext(SidebarConfigContext);\n const left = isOpen\n ? sidebarConfig.drawerWidthOpen\n : sidebarConfig.drawerWidthClosed;\n const classes = useStyles({ left, submenuConfig });\n\n const { isHoveredOn } = useContext(SidebarItemWithSubmenuContext);\n const [isSubmenuOpen, setIsSubmenuOpen] = useState(false);\n\n useEffect(() => {\n setIsSubmenuOpen(isHoveredOn);\n }, [isHoveredOn]);\n\n return (\n <Box\n className={classnames(classes.drawer, {\n [classes.drawerOpen]: isSubmenuOpen,\n })}\n >\n <Typography variant=\"h5\" component=\"span\" className={classes.title}>\n {props.title}\n </Typography>\n {props.children}\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 type { Location, Path } from 'history';\nimport { isEqual, isMatch } from 'lodash';\nimport qs from 'qs';\n\nexport function isLocationMatch(\n currentLocation: Location,\n toLocation: Path,\n exact: boolean = false,\n) {\n const toDecodedSearch = new URLSearchParams(toLocation.search).toString();\n const toQueryParameters = qs.parse(toDecodedSearch);\n\n const currentDecodedSearch = new URLSearchParams(\n currentLocation.search,\n ).toString();\n const currentQueryParameters = qs.parse(currentDecodedSearch);\n\n const queryStringMatcher = exact ? isEqual : isMatch;\n\n const matching =\n isEqual(toLocation.pathname, currentLocation.pathname) &&\n queryStringMatcher(currentQueryParameters, toQueryParameters);\n\n return matching;\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 IconComponent,\n useAnalytics,\n useElementFilter,\n} from '@backstage/core-plugin-api';\nimport Badge from '@material-ui/core/Badge';\nimport Box from '@material-ui/core/Box';\nimport { makeStyles, styled, Theme } from '@material-ui/core/styles';\nimport {\n CreateCSSProperties,\n StyledComponentProps,\n} from '@material-ui/core/styles/withStyles';\nimport TextField from '@material-ui/core/TextField';\nimport Typography from '@material-ui/core/Typography';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport ArrowDropDown from '@material-ui/icons/ArrowDropDown';\nimport ArrowDropUp from '@material-ui/icons/ArrowDropUp';\nimport ArrowRightIcon from '@material-ui/icons/ArrowRight';\nimport SearchIcon from '@material-ui/icons/Search';\nimport classnames from 'classnames';\nimport type { Location } from 'history';\n\nimport {\n ComponentProps,\n ComponentType,\n CSSProperties,\n forwardRef,\n KeyboardEventHandler,\n ReactNode,\n useCallback,\n useContext,\n useMemo,\n useState,\n MouseEvent,\n ChangeEvent,\n ReactElement,\n createElement,\n} from 'react';\n\nimport {\n Link,\n NavLinkProps,\n resolvePath,\n useLocation,\n useResolvedPath,\n} from 'react-router-dom';\n\nimport {\n SidebarConfig,\n SidebarConfigContext,\n SidebarItemWithSubmenuContext,\n} from './config';\nimport DoubleArrowLeft from './icons/DoubleArrowLeft';\nimport DoubleArrowRight from './icons/DoubleArrowRight';\nimport { useSidebarOpenState } from './SidebarOpenStateContext';\nimport { SidebarSubmenu, SidebarSubmenuProps } from './SidebarSubmenu';\nimport { SidebarSubmenuItemProps } from './SidebarSubmenuItem';\nimport { isLocationMatch } from './utils';\nimport Button from '@material-ui/core/Button';\n\n/** @public */\nexport type SidebarItemClassKey =\n | 'root'\n | 'buttonItem'\n | 'closed'\n | 'open'\n | 'highlightable'\n | 'highlighted'\n | 'label'\n | 'iconContainer'\n | 'searchRoot'\n | 'searchField'\n | 'searchFieldHTMLInput'\n | 'searchContainer'\n | 'secondaryAction'\n | 'closedItemIcon'\n | 'submenuArrow'\n | 'expandButton'\n | 'arrows'\n | 'selected';\n\nconst makeSidebarStyles = (sidebarConfig: SidebarConfig) =>\n makeStyles(\n theme => ({\n root: {\n color: theme.palette.navigation.color,\n display: 'flex',\n flexFlow: 'row nowrap',\n alignItems: 'center',\n height: 48,\n cursor: 'pointer',\n },\n buttonItem: {\n background: 'none',\n border: 'none',\n width: '100%',\n margin: 0,\n padding: 0,\n textAlign: 'inherit',\n font: 'inherit',\n textTransform: 'none',\n },\n closed: {\n width: sidebarConfig.drawerWidthClosed,\n justifyContent: 'center',\n },\n open: {\n [theme.breakpoints.up('sm')]: {\n width: sidebarConfig.drawerWidthOpen,\n },\n },\n highlightable: {\n '&:hover': {\n background:\n theme.palette.navigation.navItem?.hoverBackground ?? '#404040',\n },\n },\n highlighted: {\n background:\n theme.palette.navigation.navItem?.hoverBackground ?? '#404040',\n },\n label: {\n // XXX (@koroeskohr): I can't seem to achieve the desired font-weight from the designs\n fontWeight: 'bold',\n whiteSpace: 'nowrap',\n lineHeight: 'auto',\n flex: '3 1 auto',\n width: '110px',\n overflow: 'hidden',\n 'text-overflow': 'ellipsis',\n },\n iconContainer: {\n boxSizing: 'border-box',\n height: '100%',\n width: sidebarConfig.iconContainerWidth,\n marginRight: -theme.spacing(2),\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n lineHeight: '0',\n },\n searchRoot: {\n marginBottom: 12,\n },\n searchField: {\n color: '#b5b5b5',\n fontWeight: theme.typography.fontWeightBold,\n fontSize: theme.typography.fontSize,\n },\n searchFieldHTMLInput: {\n padding: theme.spacing(2, 0, 2),\n },\n searchContainer: {\n width: sidebarConfig.drawerWidthOpen - sidebarConfig.iconContainerWidth,\n },\n secondaryAction: {\n width: theme.spacing(6),\n textAlign: 'center',\n marginRight: theme.spacing(1),\n },\n closedItemIcon: {\n width: '100%',\n justifyContent: 'center',\n },\n submenuArrow: {\n display: 'flex',\n },\n expandButton: {\n background: 'none',\n border: 'none',\n color: theme.palette.navigation.color,\n width: '100%',\n cursor: 'pointer',\n position: 'relative',\n height: 48,\n },\n arrows: {\n position: 'absolute',\n right: 10,\n },\n selected: {\n '&$root': {\n borderLeft: `solid ${sidebarConfig.selectedIndicatorWidth}px ${theme.palette.navigation.indicator}`,\n color: theme.palette.navigation.selectedColor,\n },\n '&$closed': {\n width: sidebarConfig.drawerWidthClosed,\n },\n '& $closedItemIcon': {\n paddingRight: sidebarConfig.selectedIndicatorWidth,\n },\n '& $iconContainer': {\n marginLeft: -sidebarConfig.selectedIndicatorWidth,\n },\n },\n }),\n { name: 'BackstageSidebarItem' },\n );\n\n// This is a workaround for this issue https://github.com/mui/material-ui/issues/15511\n// The styling of the `selected` elements doesn't work as expected when using a prop callback.\n// Don't use this pattern unless needed\nfunction useMemoStyles(sidebarConfig: SidebarConfig) {\n const useStyles = useMemo(\n () => makeSidebarStyles(sidebarConfig),\n [sidebarConfig],\n );\n return useStyles();\n}\n\n/**\n * Evaluates the routes of the SubmenuItems & nested DropdownItems.\n * The reevaluation is only triggered, if the `locationPathname` changes, as `useElementFilter` uses memorization.\n *\n * @param submenu SidebarSubmenu component\n * @param location Location\n * @returns boolean\n */\nconst useLocationMatch = (\n submenu: ReactElement<SidebarSubmenuProps>,\n location: Location,\n): boolean =>\n useElementFilter(\n submenu.props.children,\n elements => {\n let active = false;\n elements\n .getElements()\n .forEach(\n ({\n props: { to, dropdownItems },\n }: {\n props: Partial<SidebarSubmenuItemProps>;\n }) => {\n if (!active) {\n if (dropdownItems?.length) {\n dropdownItems.forEach(\n ({ to: _to }) =>\n (active =\n active || isLocationMatch(location, resolvePath(_to))),\n );\n return;\n }\n if (to) {\n active = isLocationMatch(location, resolvePath(to));\n }\n }\n },\n );\n return active;\n },\n [location.pathname],\n );\n\ntype SidebarItemBaseProps = {\n icon: IconComponent;\n text?: string;\n hasNotifications?: boolean;\n hasSubmenu?: boolean;\n disableHighlight?: boolean;\n className?: string;\n noTrack?: boolean;\n onClick?: (ev: MouseEvent) => void;\n};\n\ntype SidebarItemButtonProps = SidebarItemBaseProps & {\n onClick: (ev: MouseEvent) => void;\n children?: ReactNode;\n};\n\ntype SidebarItemLinkProps = SidebarItemBaseProps & {\n to: string;\n onClick?: (ev: MouseEvent) => void;\n} & NavLinkProps;\n\ntype SidebarItemWithSubmenuProps = SidebarItemBaseProps & {\n to?: string;\n onClick?: (ev: MouseEvent) => void;\n children: ReactNode;\n};\n\n/**\n * SidebarItem with 'to' property will be a clickable link.\n * SidebarItem with 'onClick' property and without 'to' property will be a clickable button.\n * SidebarItem which wraps a SidebarSubmenu will be a clickable button which opens a submenu.\n */\ntype SidebarItemProps =\n | SidebarItemLinkProps\n | SidebarItemButtonProps\n | SidebarItemWithSubmenuProps;\n\nfunction isButtonItem(\n props: SidebarItemProps,\n): props is SidebarItemButtonProps {\n return (props as SidebarItemLinkProps).to === undefined;\n}\n\nconst sidebarSubmenuType = createElement(SidebarSubmenu).type;\n\n// TODO(Rugvip): Remove this once NavLink is updated in react-router-dom.\n// This is needed because react-router doesn't handle the path comparison\n// properly yet, matching for example /foobar with /foo.\nexport const WorkaroundNavLink = forwardRef<\n HTMLAnchorElement,\n NavLinkProps & {\n children?: ReactNode;\n activeStyle?: CSSProperties;\n activeClassName?: string;\n }\n>(function WorkaroundNavLinkWithRef(\n {\n to,\n end,\n style,\n className,\n activeStyle,\n caseSensitive,\n activeClassName = 'active',\n 'aria-current': ariaCurrentProp = 'page',\n ...rest\n },\n ref,\n) {\n let { pathname: locationPathname } = useLocation();\n let { pathname: toPathname } = useResolvedPath(to);\n\n if (!caseSensitive) {\n locationPathname = locationPathname.toLocaleLowerCase('en-US');\n toPathname = toPathname.toLocaleLowerCase('en-US');\n }\n\n let isActive = locationPathname === toPathname;\n if (!isActive && !end) {\n // This is the behavior that is different from the original NavLink\n isActive = locationPathname.startsWith(`${toPathname}/`);\n }\n\n const ariaCurrent = isActive ? ariaCurrentProp : undefined;\n\n return (\n <Link\n {...rest}\n to={to}\n ref={ref}\n aria-current={ariaCurrent}\n style={{ ...style, ...(isActive ? activeStyle : undefined) }}\n className={classnames([\n typeof className !== 'function' ? className : undefined,\n isActive ? activeClassName : undefined,\n ])}\n />\n );\n});\n\n/**\n * Common component used by SidebarItem & SidebarItemWithSubmenu\n */\nconst SidebarItemBase = forwardRef<\n any,\n SidebarItemProps & { children: ReactNode }\n>((props, ref) => {\n const {\n icon: Icon,\n text,\n hasNotifications = false,\n hasSubmenu = false,\n disableHighlight = false,\n onClick,\n noTrack,\n children,\n className,\n ...navLinkProps\n } = props;\n const { sidebarConfig } = useContext(SidebarConfigContext);\n const classes = useMemoStyles(sidebarConfig);\n // XXX (@koroeskohr): unsure this is optimal. But I just really didn't want to have the item component\n // depend on the current location, and at least have it being optionally forced to selected.\n // Still waiting on a Q answered to fine tune the implementation\n const { isOpen } = useSidebarOpenState();\n\n const divStyle =\n !isOpen && hasSubmenu\n ? { display: 'flex', marginLeft: '20px' }\n : { lineHeight: '0' };\n\n const displayItemIcon = (\n <Box style={divStyle}>\n <Icon fontSize=\"small\" />\n {!isOpen && hasSubmenu ? <ArrowRightIcon fontSize=\"small\" /> : <></>}\n </Box>\n );\n\n const itemIcon = (\n <Badge\n color=\"secondary\"\n variant=\"dot\"\n overlap=\"circular\"\n invisible={!hasNotifications}\n className={classnames({ [classes.closedItemIcon]: !isOpen })}\n >\n {displayItemIcon}\n </Badge>\n );\n\n const openContent = (\n <>\n <Box data-testid=\"login-button\" className={classes.iconContainer}>\n {itemIcon}\n </Box>\n {text && (\n <Typography\n variant=\"subtitle2\"\n component=\"span\"\n className={classes.label}\n >\n {text}\n </Typography>\n )}\n <div className={classes.secondaryAction}>{children}</div>\n </>\n );\n\n const content = isOpen ? openContent : itemIcon;\n\n const childProps = {\n onClick,\n className: classnames(\n className,\n classes.root,\n isOpen ? classes.open : classes.closed,\n isButtonItem(props) && classes.buttonItem,\n { [classes.highlightable]: !disableHighlight },\n ),\n };\n\n const analyticsApi = useAnalytics();\n const { pathname: to } = useResolvedPath(\n !isButtonItem(props) && props.to ? props.to : '',\n );\n\n const handleClick = useCallback(\n (event: MouseEvent<HTMLAnchorElement | HTMLButtonElement>) => {\n if (!noTrack) {\n const action = 'click';\n const subject = text ?? 'Sidebar Item';\n const options = to ? { attributes: { to } } : undefined;\n analyticsApi.captureEvent(action, subject, options);\n }\n onClick?.(event);\n },\n [analyticsApi, text, to, noTrack, onClick],\n );\n\n if (isButtonItem(props)) {\n return (\n <Button\n role=\"button\"\n aria-label={text}\n {...childProps}\n ref={ref}\n onClick={handleClick}\n >\n {content}\n </Button>\n );\n }\n\n return (\n <WorkaroundNavLink\n {...childProps}\n activeClassName={classes.selected}\n to={props.to ? props.to : ''}\n ref={ref}\n aria-label={text ? text : props.to}\n {...navLinkProps}\n onClick={handleClick}\n >\n {content}\n </WorkaroundNavLink>\n );\n});\n\nconst SidebarItemWithSubmenu = ({\n children,\n ...props\n}: SidebarItemBaseProps & {\n children: ReactElement<SidebarSubmenuProps>;\n}) => {\n const { sidebarConfig } = useContext(SidebarConfigContext);\n const classes = useMemoStyles(sidebarConfig);\n const [isHoveredOn, setIsHoveredOn] = useState(false);\n const location = useLocation();\n const isActive = useLocationMatch(children, location);\n const isSmallScreen = useMediaQuery((theme: Theme) =>\n theme.breakpoints.down('sm'),\n );\n\n const handleMouseEnter = () => {\n setIsHoveredOn(true);\n };\n const handleMouseLeave = () => {\n setIsHoveredOn(false);\n };\n\n const arrowIcon = () => {\n if (isSmallScreen) {\n return isHoveredOn ? (\n <ArrowDropUp fontSize=\"small\" className={classes.submenuArrow} />\n ) : (\n <ArrowDropDown fontSize=\"small\" className={classes.submenuArrow} />\n );\n }\n return (\n !isHoveredOn && (\n <ArrowRightIcon fontSize=\"small\" className={classes.submenuArrow} />\n )\n );\n };\n\n return (\n <SidebarItemWithSubmenuContext.Provider\n value={{\n isHoveredOn,\n setIsHoveredOn,\n }}\n >\n <div\n data-testid=\"item-with-submenu\"\n onMouseLeave={handleMouseLeave}\n onTouchStart={isHoveredOn ? handleMouseLeave : handleMouseEnter}\n onMouseEnter={handleMouseEnter}\n className={classnames(isHoveredOn && classes.highlighted)}\n >\n <SidebarItemBase\n hasSubmenu\n className={isActive ? classes.selected : ''}\n {...props}\n >\n {arrowIcon()}\n </SidebarItemBase>\n {isHoveredOn && children}\n </div>\n </SidebarItemWithSubmenuContext.Provider>\n );\n};\n\n/**\n * Creates a `SidebarItem`\n *\n * @remarks\n * If children contain a `SidebarSubmenu` component the `SidebarItem` will have a expandable submenu\n */\nexport const SidebarItem = forwardRef<\n any,\n SidebarItemProps & { children: ReactNode }\n>((props, ref) => {\n // Filter children for SidebarSubmenu components\n const [submenu] = useElementFilter(props.children, elements =>\n // Directly comparing child.type with SidebarSubmenu will not work with in\n // combination with react-hot-loader\n //\n // https://github.com/gaearon/react-hot-loader/issues/304#issuecomment-456569720\n elements.getElements().filter(child => child.type === sidebarSubmenuType),\n );\n\n if (submenu) {\n return (\n <SidebarItemWithSubmenu {...props}>\n {submenu as ReactElement<SidebarSubmenuProps>}\n </SidebarItemWithSubmenu>\n );\n }\n\n return <SidebarItemBase {...props} ref={ref} />;\n}) as (props: SidebarItemProps) => JSX.Element;\n\ntype SidebarSearchFieldProps = {\n onSearch: (input: string) => void;\n to?: string;\n icon?: IconComponent;\n};\n\nexport function SidebarSearchField(props: SidebarSearchFieldProps) {\n const { sidebarConfig } = useContext(SidebarConfigContext);\n const [input, setInput] = useState('');\n const classes = useMemoStyles(sidebarConfig);\n const Icon = props.icon ? props.icon : SearchIcon;\n\n const search = () => {\n props.onSearch(input);\n setInput('');\n };\n\n const handleEnter: KeyboardEventHandler = ev => {\n if (ev.key === 'Enter') {\n ev.preventDefault();\n search();\n }\n };\n\n const handleInput = (ev: ChangeEvent<HTMLInputElement>) => {\n setInput(ev.target.value);\n };\n\n const handleInputClick = (ev: MouseEvent<HTMLInputElement>) => {\n // Clicking into the search fields shouldn't navigate to the search page\n ev.preventDefault();\n ev.stopPropagation();\n };\n\n const handleItemClick = (ev: MouseEvent) => {\n // Clicking on the search icon while should execute a query with the current field content\n search();\n ev.preventDefault();\n };\n\n return (\n <Box className={classes.searchRoot}>\n <SidebarItem\n icon={Icon}\n to={props.to}\n onClick={handleItemClick}\n disableHighlight\n >\n <TextField\n placeholder=\"Search\"\n value={input}\n onClick={handleInputClick}\n onChange={handleInput}\n onKeyDown={handleEnter}\n className={classes.searchContainer}\n InputProps={{\n disableUnderline: true,\n className: classes.searchField,\n }}\n inputProps={{\n className: classes.searchFieldHTMLInput,\n }}\n />\n </SidebarItem>\n </Box>\n );\n}\n\nexport type SidebarSpaceClassKey = 'root';\n\nexport const SidebarSpace = styled('div')(\n {\n flex: 1,\n },\n { name: 'BackstageSidebarSpace' },\n) as ComponentType<ComponentProps<'div'> & StyledComponentProps<'root'>>;\n\nexport type SidebarSpacerClassKey = 'root';\n\nexport const SidebarSpacer = styled('div')(\n {\n height: 8,\n },\n { name: 'BackstageSidebarSpacer' },\n) as ComponentType<ComponentProps<'div'> & StyledComponentProps<'root'>>;\n\nexport type SidebarDividerClassKey = 'root';\n\nexport const SidebarDivider = styled('hr')(\n ({ theme }) => ({\n height: 1,\n width: '100%',\n background: '#383838',\n border: 'none',\n margin: theme.spacing(1.2, 0),\n }),\n { name: 'BackstageSidebarDivider' },\n) as ComponentType<ComponentProps<'hr'> & StyledComponentProps<'root'>>;\n\nconst styledScrollbar = (theme: Theme): CreateCSSProperties => ({\n overflowY: 'auto',\n '&::-webkit-scrollbar': {\n backgroundColor: theme.palette.background.default,\n width: '5px',\n borderRadius: '5px',\n },\n '&::-webkit-scrollbar-thumb': {\n backgroundColor: theme.palette.text.secondary,\n borderRadius: '5px',\n },\n});\n\nexport const SidebarScrollWrapper = styled('div')(({ theme }) => {\n const scrollbarStyles = styledScrollbar(theme);\n return {\n flex: '0 1 auto',\n overflowX: 'hidden',\n width: '100%',\n // Display at least one item in the container\n // Question: Can this be a config/theme variable - if so, which? :/\n minHeight: '48px',\n overflowY: 'hidden',\n '@media (hover: none)': scrollbarStyles,\n '&:hover': scrollbarStyles,\n };\n}) as ComponentType<ComponentProps<'div'> & StyledComponentProps<'root'>>;\n\n/**\n * A button which allows you to expand the sidebar when clicked.\n *\n * @remarks\n * Use optionally to replace sidebar's expand-on-hover feature with expand-on-click.\n *\n * If you are using this you might want to set the `disableExpandOnHover` of the `Sidebar` to `true`.\n *\n * @public\n */\nexport const SidebarExpandButton = () => {\n const { sidebarConfig } = useContext(SidebarConfigContext);\n const classes = useMemoStyles(sidebarConfig);\n const { isOpen, setOpen } = useSidebarOpenState();\n const isSmallScreen = useMediaQuery<Theme>(\n theme => theme.breakpoints.down('md'),\n { noSsr: true },\n );\n\n if (isSmallScreen) {\n return null;\n }\n\n const handleClick = () => {\n setOpen(!isOpen);\n };\n\n return (\n <Button\n role=\"button\"\n onClick={handleClick}\n className={classes.expandButton}\n aria-label=\"Expand Sidebar\"\n data-testid=\"sidebar-expand-button\"\n >\n <Box className={classes.arrows}>\n {isOpen ? <DoubleArrowLeft /> : <DoubleArrowRight />}\n </Box>\n </Button>\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 { PropsWithChildren } from 'react';\n\nimport { makeStyles } from '@material-ui/core/styles';\nimport LibraryBooks from '@material-ui/icons/LibraryBooks';\nimport LogoFull from './LogoFull';\nimport LogoIcon from './LogoIcon';\n\nimport {\n Sidebar,\n SidebarItem,\n SidebarPage,\n sidebarConfig,\n SidebarDivider,\n useSidebarOpenState,\n Link,\n} from '@backstage/core-components';\n\nconst useSidebarLogoStyles = makeStyles({\n root: {\n width: sidebarConfig.drawerWidthClosed,\n height: 3 * sidebarConfig.logoHeight,\n display: 'flex',\n flexFlow: 'row nowrap',\n alignItems: 'center',\n marginBottom: -14,\n },\n link: {\n width: sidebarConfig.drawerWidthClosed,\n marginLeft: 24,\n },\n});\n\nconst SidebarLogo = () => {\n const classes = useSidebarLogoStyles();\n const { isOpen } = useSidebarOpenState();\n\n return (\n <div className={classes.root}>\n <Link\n to=\"/docs/default/component/local/\"\n underline=\"none\"\n className={classes.link}\n >\n {isOpen ? <LogoFull /> : <LogoIcon />}\n </Link>\n </div>\n );\n};\n\nexport const Root = ({ children }: PropsWithChildren<{}>) => (\n <SidebarPage>\n <Sidebar>\n <SidebarLogo />\n <SidebarDivider />\n {/* Global nav, not org-specific */}\n <SidebarItem\n icon={LibraryBooks}\n to=\"/docs/default/component/local\"\n text=\"Docs Preview\"\n />\n {/* End global nav */}\n </Sidebar>\n {children}\n </SidebarPage>\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 { useState } from 'react';\n\nimport { makeStyles } from '@material-ui/core/styles';\nimport { Theme } from '@material-ui/core/styles/createTheme';\n\nimport Box from '@material-ui/core/Box';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport IconButton from '@material-ui/core/IconButton';\nimport LightIcon from '@material-ui/icons/Brightness7';\nimport DarkIcon from '@material-ui/icons/Brightness4';\n\nimport { appThemeApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport {\n TechDocsReaderPage,\n TechDocsReaderPageHeader,\n TechDocsReaderPageContent,\n} from '@backstage/plugin-techdocs';\n\nconst useStyles = makeStyles((theme: Theme) => ({\n headerIcon: {\n color: theme.palette.common.white,\n width: '32px',\n height: '32px',\n },\n content: {\n backgroundColor: theme.palette.background.default,\n },\n contentToolbar: {\n display: 'flex',\n justifyContent: 'flex-end',\n padding: 0,\n },\n}));\n\nenum Themes {\n LIGHT = 'light',\n DARK = 'dark',\n}\n\nexport const TechDocsThemeToggle = () => {\n const appThemeApi = useApi(appThemeApiRef);\n const classes = useStyles();\n const [theme, setTheme] = useState<Themes>(\n appThemeApi.getActiveThemeId() === Themes.DARK ? Themes.DARK : Themes.LIGHT,\n );\n\n const themes = {\n [Themes.LIGHT]: {\n icon: DarkIcon,\n title: 'Dark theme',\n },\n [Themes.DARK]: {\n icon: LightIcon,\n title: 'Light theme',\n },\n };\n\n const { title, icon: Icon } = themes[theme];\n\n const handleSetTheme = () => {\n setTheme(prevTheme => {\n const newTheme = prevTheme === Themes.LIGHT ? Themes.DARK : Themes.LIGHT;\n appThemeApi.setActiveThemeId(newTheme);\n return newTheme;\n });\n };\n\n return (\n <Box display=\"flex\" alignItems=\"center\" mr={2}>\n <Tooltip title={title} arrow>\n <IconButton size=\"small\" onClick={handleSetTheme}>\n <Icon className={classes.headerIcon} />\n </IconButton>\n </Tooltip>\n </Box>\n );\n};\n\nconst DefaultTechDocsPage = () => {\n return (\n <TechDocsReaderPage>\n <TechDocsReaderPageHeader />\n <TechDocsReaderPageContent withSearch={false} />\n </TechDocsReaderPage>\n );\n};\n\nexport const techDocsPage = <DefaultTechDocsPage />;\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 { Navigate, Route } from 'react-router-dom';\n\nimport {\n DefaultTechDocsHome,\n TechDocsIndexPage,\n TechDocsReaderPage,\n techdocsPlugin,\n} from '@backstage/plugin-techdocs';\nimport {\n createTechDocsAddonExtension,\n TechDocsAddons,\n TechDocsAddonLocations,\n} from '@backstage/plugin-techdocs-react';\nimport { createApp } from '@backstage/app-defaults';\nimport { FlatRoutes } from '@backstage/core-app-api';\nimport { CatalogEntityPage } from '@backstage/plugin-catalog';\n\nimport { apis } from './apis';\nimport * as plugins from './plugins';\nimport { configLoader } from './config';\nimport { Root } from './components/Root';\nimport { techDocsPage, TechDocsThemeToggle } from './components/TechDocsPage';\n\nconst app = createApp({\n apis,\n configLoader,\n plugins: Object.values(plugins),\n});\n\nconst AppProvider = app.getProvider();\nconst AppRouter = app.getRouter();\n\nconst ThemeToggleAddon = techdocsPlugin.provide(\n createTechDocsAddonExtension({\n name: 'ThemeToggleAddon',\n component: TechDocsThemeToggle,\n location: TechDocsAddonLocations.Header,\n }),\n);\n\nconst routes = (\n <FlatRoutes>\n <Navigate key=\"/\" to=\"/docs/default/component/local/\" />\n {/* we need this route as TechDocs header links relies on it */}\n <Route\n path=\"/catalog/:namespace/:kind/:name\"\n element={<CatalogEntityPage />}\n />\n <Route path=\"/docs\" element={<TechDocsIndexPage />}>\n <DefaultTechDocsHome />\n </Route>\n <Route\n path=\"/docs/:namespace/:kind/:name/*\"\n element={<TechDocsReaderPage />}\n >\n {techDocsPage}\n <TechDocsAddons>\n <ThemeToggleAddon />\n </TechDocsAddons>\n </Route>\n </FlatRoutes>\n);\n\nconst App = () => (\n <AppProvider>\n <AppRouter>\n <Root>{routes}</Root>\n </AppRouter>\n </AppProvider>\n);\n\nexport default App;\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 { AppManager } from './AppManager';\nimport { AppOptions, BackstageApp } from './types';\n\n/**\n * Creates a new Backstage App where the full set of options are required.\n *\n * @public\n * @param options - A set of options for creating the app\n * @returns\n * @remarks\n *\n * You will most likely want to use {@link @backstage/app-defaults#createApp},\n * however, this low-level API allows you to provide a full set of options,\n * including your own `components`, `icons`, `defaultApis`, and `themes`. This\n * is particularly useful if you are not using `@backstage/core-components` or\n * Material UI, as it allows you to avoid those dependencies completely.\n */\nexport function createSpecializedApp(options: AppOptions): BackstageApp {\n return new AppManager(options);\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 '@backstage/cli/asset-types';\nimport ReactDOM from 'react-dom/client';\nimport App from './App';\n\nReactDOM.createRoot(document.getElementById('root')!).render(<App />);\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 { createContext, useContext, Context } from 'react';\nimport { getOrCreateGlobalSingleton } from './globalObject';\nimport { createVersionedValueMap, VersionedValue } from './VersionedValue';\n\n/**\n * Get the existing or create a new versioned React context that's\n * stored inside a global singleton.\n *\n * @param key - A key that uniquely identifies the context.\n * @public\n * @example\n *\n * ```ts\n * const MyContext = createVersionedContext<{ 1: string }>('my-context');\n *\n * const MyContextProvider = ({children}) => (\n * <MyContext.Provider value={createVersionedValueMap({ 1: 'value-for-version-1' })}>\n * {children}\n * <MyContext.Provider>\n * )\n * ```\n */\nexport function createVersionedContext<\n Versions extends { [version in number]: unknown },\n>(key: string): Context<VersionedValue<Versions> | undefined> {\n return getOrCreateGlobalSingleton(key, () =>\n createContext<VersionedValue<Versions> | undefined>(undefined),\n );\n}\n\n/**\n * A hook that simplifies the consumption of a versioned contexts that's\n * stored inside a global singleton.\n *\n * @param key - A key that uniquely identifies the context.\n * @public\n * @example\n *\n * ```ts\n * const versionedHolder = useVersionedContext<{ 1: string }>('my-context');\n *\n * if (!versionedHolder) {\n * throw new Error('My context is not available!')\n * }\n *\n * const myValue = versionedHolder.atVersion(1);\n *\n * // ...\n * ```\n */\nexport function useVersionedContext<\n Versions extends { [version in number]: unknown },\n>(key: string): VersionedValue<Versions> | undefined {\n return useContext(createVersionedContext<Versions>(key));\n}\n\n/**\n * Creates a helper for writing tests towards multiple different\n * combinations of versions provided from a context.\n *\n * @param key - A key that uniquely identifies the context.\n * @public\n * @example\n *\n * ```ts\n * const context = createVersionedContextForTesting('my-context');\n *\n * afterEach(() => {\n * context.reset();\n * });\n *\n * it('should work when provided with version 1', () => {\n * context.set({1: 'value-for-version-1'})\n *\n * // ...\n * })\n * ```\n */\nexport function createVersionedContextForTesting(key: string) {\n return {\n set(versions: { [version in number]: unknown }) {\n (globalThis as any)[`__@backstage/${key}__`] = createContext(\n createVersionedValueMap(versions),\n );\n },\n reset() {\n delete (globalThis as any)[`__@backstage/${key}__`];\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\n/**\n * The versioned value interface is a container for a set of values that\n * can be looked up by version. It is intended to be used as a container\n * for values that can be versioned independently of package versions.\n *\n * @public\n */\nexport type VersionedValue<Versions extends { [version: number]: unknown }> = {\n atVersion<Version extends keyof Versions>(\n version: Version,\n ): Versions[Version] | undefined;\n};\n\n/**\n * Creates a container for a map of versioned values that implements VersionedValue.\n *\n * @public\n */\nexport function createVersionedValueMap<\n Versions extends { [version: number]: unknown },\n>(versions: Versions): VersionedValue<Versions> {\n Object.freeze(versions);\n const versionedValue: VersionedValue<Versions> = {\n atVersion(version) {\n return versions[version];\n },\n };\n Object.defineProperty(versionedValue, '$map', {\n configurable: true,\n enumerable: true,\n get() {\n return versions;\n },\n });\n return versionedValue;\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\n// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028\nfunction getGlobalObject() {\n if (typeof window !== 'undefined' && window.Math === Math) {\n return window;\n }\n // eslint-disable-next-line no-restricted-globals\n if (typeof self !== 'undefined' && self.Math === Math) {\n // eslint-disable-next-line no-restricted-globals\n return self;\n }\n // eslint-disable-next-line no-new-func\n return Function('return this')();\n}\n\nconst globalObject = getGlobalObject();\n\nconst makeKey = (id: string) => `__@backstage/${id}__`;\n\n/**\n * Serializes access to a global singleton value, with the first caller creating the value.\n *\n * @public\n */\nexport function getOrCreateGlobalSingleton<T>(\n id: string,\n supplier: () => T,\n): T {\n const key = makeKey(id);\n\n let value = globalObject[key];\n if (value) {\n return value;\n }\n\n value = supplier();\n globalObject[key] = value;\n return value;\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 { CatalogApi } from '@backstage/catalog-client';\nimport { createApiRef } from '@backstage/core-plugin-api';\n\n/**\n * The API reference for the {@link @backstage/catalog-client#CatalogApi}.\n * @public\n */\nexport const catalogApiRef = createApiRef<CatalogApi>({\n id: 'plugin.catalog.service',\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 { Entity } from '@backstage/catalog-model';\nimport {\n ApiRef,\n IconComponent,\n createApiRef,\n} from '@backstage/core-plugin-api';\nimport { Observable } from '@backstage/types';\n\n/**\n * An API that handles how to represent entities in the interface.\n *\n * @public\n */\nexport const entityPresentationApiRef: ApiRef<EntityPresentationApi> =\n createApiRef({\n id: 'plugin.catalog.entity-presentation',\n });\n\n/**\n * The visual presentation of an entity reference at some point in time.\n *\n * @public\n */\nexport interface EntityRefPresentationSnapshot {\n /**\n * The ref to the entity that this snapshot represents.\n *\n * @remarks\n *\n * Note that when the input data was broken or had missing vital pieces of\n * information, this string may contain placeholders such as \"unknown\". You\n * can therefore not necessarily assume that the ref is completely valid and\n * usable for example for forming a clickable link to the entity.\n */\n entityRef: string;\n /**\n * A string that can be used as a plain representation of the entity, for\n * example in a header or a link.\n *\n * @remarks\n *\n * The title may be short and not contain all of the information that the\n * entity holds. When rendering the primary title, you may also want to\n * make sure to add more contextual information nearby such as the icon or\n * secondary title, since the primary could for example just be the\n * `metadata.name` of the entity which might be ambiguous to the reader.\n */\n primaryTitle: string;\n /**\n * Optionally, some additional textual information about the entity, to be\n * used as a clarification on top of the primary title.\n *\n * @remarks\n *\n * This text can for example be rendered in a tooltip or be used as a\n * subtitle. It may not be sufficient to display on its own; it should\n * typically be used in conjunction with the primary title. It can contain\n * such information as the entity ref and/or a `spec.type` etc.\n */\n secondaryTitle?: string;\n /**\n * Optionally, an icon that represents the kind/type of entity.\n *\n * @remarks\n *\n * This icon should ideally be easily recognizable as the kind of entity, and\n * be used consistently throughout the Backstage interface. It can be rendered\n * both in larger formats such as in a header, or in smaller formats such as\n * inline with regular text, so bear in mind that the legibility should be\n * high in both cases.\n *\n * A value of `false` here indicates the desire to not have an icon present\n * for the given implementation. A value of `undefined` leaves it at the\n * discretion of the display layer to choose what to do (such as for example\n * showing a fallback icon).\n */\n Icon?: IconComponent | undefined | false;\n}\n\n/**\n * The visual presentation of an entity reference.\n *\n * @public\n */\nexport interface EntityRefPresentation {\n /**\n * The representation that's suitable to use for this entity right now.\n */\n snapshot: EntityRefPresentationSnapshot;\n /**\n * Some presentation implementations support emitting updated snapshots over\n * time, for example after retrieving additional data from the catalog or\n * elsewhere.\n */\n update$?: Observable<EntityRefPresentationSnapshot>;\n /**\n * A promise that resolves to a usable entity presentation.\n */\n promise: Promise<EntityRefPresentationSnapshot>;\n}\n\n/**\n * An API that decides how to visually represent entities in the interface.\n *\n * @remarks\n *\n * Most consumers will want to use the {@link useEntityPresentation} hook\n * instead of this interface directly.\n *\n * @public\n */\nexport interface EntityPresentationApi {\n /**\n * Fetches the presentation for an entity.\n *\n * @param entityOrRef - Either an entity, or a string ref to it. If you pass\n * in an entity, it is assumed that it is not a partial one - i.e. only pass\n * in an entity if you know that it was fetched in such a way that it\n * contains all of the fields that the representation renderer needs.\n * @param context - Contextual information that may affect the presentation.\n */\n forEntity(\n entityOrRef: Entity | string,\n context?: {\n defaultKind?: string;\n defaultNamespace?: string;\n },\n ): EntityRefPresentation;\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 {\n CompoundEntityRef,\n DEFAULT_NAMESPACE,\n Entity,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport get from 'lodash/get';\nimport { EntityRefPresentationSnapshot } from './EntityPresentationApi';\n\n/**\n * This returns the default representation of an entity.\n *\n * @public\n * @param entityOrRef - Either an entity, or a ref to it.\n * @param context - Contextual information that may affect the presentation.\n */\nexport function defaultEntityPresentation(\n entityOrRef: Entity | CompoundEntityRef | string,\n context?: {\n defaultKind?: string;\n defaultNamespace?: string;\n },\n): EntityRefPresentationSnapshot {\n // NOTE(freben): This code may look convoluted, but it tries its very best to\n // be defensive and handling any type of malformed input and still producing\n // some form of result without crashing.\n const { kind, namespace, name, title, description, displayName, type } =\n getParts(entityOrRef);\n\n const entityRef: string = stringifyEntityRef({\n kind: kind || 'unknown',\n namespace: namespace || DEFAULT_NAMESPACE,\n name: name || 'unknown',\n });\n\n const shortRef = getShortRef({ kind, namespace, name, context });\n\n const primary = [displayName, title, shortRef].find(\n candidate => candidate && typeof candidate === 'string',\n )!;\n\n const secondary = [\n primary !== entityRef ? entityRef : undefined,\n type,\n description,\n ]\n .filter(candidate => candidate && typeof candidate === 'string')\n .join(' | ');\n\n return {\n entityRef,\n primaryTitle: primary,\n secondaryTitle: secondary || undefined,\n Icon: undefined, // leave it up to the presentation API to handle\n };\n}\n\nconst isString = (value: unknown): value is string =>\n Boolean(value) && typeof value === 'string';\n\n// Try to extract display-worthy parts of an entity or ref as best we can, without throwing\nfunction getParts(entityOrRef: Entity | CompoundEntityRef | string): {\n kind?: string;\n namespace?: string;\n name?: string;\n title?: string;\n description?: string;\n displayName?: string;\n type?: string;\n} {\n if (typeof entityOrRef === 'string') {\n let colonI = entityOrRef.indexOf(':');\n const slashI = entityOrRef.indexOf('/');\n\n // If the / is ahead of the :, treat the rest as the name\n if (slashI !== -1 && slashI < colonI) {\n colonI = -1;\n }\n\n const kind = colonI === -1 ? undefined : entityOrRef.slice(0, colonI);\n const namespace =\n slashI === -1 ? undefined : entityOrRef.slice(colonI + 1, slashI);\n const name = entityOrRef.slice(Math.max(colonI + 1, slashI + 1));\n\n return { kind, namespace, name };\n }\n\n if (typeof entityOrRef === 'object' && entityOrRef !== null) {\n const kind = [get(entityOrRef, 'kind')].find(isString);\n\n const namespace = [\n get(entityOrRef, 'metadata.namespace'),\n get(entityOrRef, 'namespace'),\n ].find(isString);\n\n const name = [\n get(entityOrRef, 'metadata.name'),\n get(entityOrRef, 'name'),\n ].find(isString);\n\n const title = [get(entityOrRef, 'metadata.title')].find(isString);\n\n const description = [get(entityOrRef, 'metadata.description')].find(\n isString,\n );\n\n const displayName = [get(entityOrRef, 'spec.profile.displayName')].find(\n isString,\n );\n\n const type = [get(entityOrRef, 'spec.type')].find(isString);\n\n return { kind, namespace, name, title, description, displayName, type };\n }\n\n return {};\n}\n\nfunction getShortRef(options: {\n kind?: string;\n namespace?: string;\n name?: string;\n context?: { defaultKind?: string; defaultNamespace?: string };\n}): string {\n const kind = options.kind?.toLocaleLowerCase('en-US') || 'unknown';\n const namespace = options.namespace || DEFAULT_NAMESPACE;\n const name = options.name || 'unknown';\n const defaultKindLower =\n options.context?.defaultKind?.toLocaleLowerCase('en-US');\n const defaultNamespaceLower =\n options.context?.defaultNamespace?.toLocaleLowerCase('en-US');\n\n let result = name;\n\n if (\n (defaultNamespaceLower &&\n namespace.toLocaleLowerCase('en-US') !== defaultNamespaceLower) ||\n namespace !== DEFAULT_NAMESPACE\n ) {\n result = `${namespace}/${result}`;\n }\n\n if (\n defaultKindLower &&\n kind.toLocaleLowerCase('en-US') !== defaultKindLower\n ) {\n result = `${kind}:${result}`;\n }\n\n return result;\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 {\n CompoundEntityRef,\n Entity,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { useApiHolder } from '@backstage/core-plugin-api';\nimport { useMemo } from 'react';\nimport {\n EntityRefPresentation,\n EntityRefPresentationSnapshot,\n entityPresentationApiRef,\n} from './EntityPresentationApi';\nimport { defaultEntityPresentation } from './defaultEntityPresentation';\nimport { useUpdatingObservable } from './useUpdatingObservable';\n\n/**\n * Returns information about how to represent an entity in the interface.\n *\n * @public\n * @param entityOrRef - The entity to represent, or an entity ref to it. If you\n * pass in an entity, it is assumed that it is NOT a partial one - i.e. only\n * pass in an entity if you know that it was fetched in such a way that it\n * contains all of the fields that the representation renderer needs.\n * @param context - Optional context that control details of the presentation.\n * @returns A snapshot of the entity presentation, which may change over time\n */\nexport function useEntityPresentation(\n entityOrRef: Entity | CompoundEntityRef | string,\n context?: {\n defaultKind?: string;\n defaultNamespace?: string;\n },\n): EntityRefPresentationSnapshot {\n // Defensively allow for a missing presentation API, which makes this hook\n // safe to use in tests.\n const apis = useApiHolder();\n const entityPresentationApi = apis.get(entityPresentationApiRef);\n\n const deps = [\n entityPresentationApi,\n JSON.stringify(entityOrRef),\n JSON.stringify(context || null),\n ];\n\n const presentation = useMemo<EntityRefPresentation>(\n () => {\n if (!entityPresentationApi) {\n const fallback = defaultEntityPresentation(entityOrRef, context);\n return { snapshot: fallback, promise: Promise.resolve(fallback) };\n }\n\n return entityPresentationApi.forEntity(\n typeof entityOrRef === 'string' || 'metadata' in entityOrRef\n ? entityOrRef\n : stringifyEntityRef(entityOrRef),\n context,\n );\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n deps,\n );\n\n // NOTE(freben): We intentionally do not use the plain useObservable from the\n // react-use library here. That hook does not support a dependencies array,\n // and also it only subscribes once to the initially passed in observable and\n // won't properly react when either initial value or the actual observable\n // changes.\n return useUpdatingObservable(presentation.snapshot, presentation.update$, [\n presentation,\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 { Observable } from '@backstage/types';\nimport { DependencyList, useEffect, useState } from 'react';\n\n/**\n * Subscribe to an observable and return the latest value from it.\n *\n * @remarks\n *\n * This implementation differs in a few important ways from the plain\n * useObservable from the react-use library. That hook does not support a\n * dependencies array, and also it only subscribes once to the initially passed\n * in observable and won't properly react when either initial value or the\n * actual observable changes.\n *\n * This hook will ensure to resubscribe and reconsider the initial value,\n * whenever the dependencies change.\n */\nexport function useUpdatingObservable<T>(\n value: T,\n observable: Observable<T> | undefined,\n deps: DependencyList,\n): T {\n const [snapshot, setSnapshot] = useState(value);\n\n useEffect(() => {\n setSnapshot(value);\n\n const subscription = observable?.subscribe({\n next: updatedValue => {\n setSnapshot(updatedValue);\n },\n complete: () => {\n subscription?.unsubscribe();\n },\n });\n\n return () => {\n subscription?.unsubscribe();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n\n return snapshot;\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 { ApiRef, createApiRef } from '@backstage/core-plugin-api';\nimport { Observable } from '@backstage/types';\n\n/**\n * An API to store starred entities\n *\n * @public\n */\nexport const starredEntitiesApiRef: ApiRef<StarredEntitiesApi> = createApiRef({\n id: 'catalog-react.starred-entities',\n});\n\n/**\n * An API to store and retrieve starred entities\n *\n * @public\n */\nexport interface StarredEntitiesApi {\n /**\n * Toggle the star state of the entity\n *\n * @param entityRef - an entity reference to toggle\n */\n toggleStarred(entityRef: string): Promise<void>;\n\n /**\n * Observe the set of starred entity references.\n */\n starredEntitie$(): Observable<Set<string>>;\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 { 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 { 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};\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 } = 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 renderOption={(option, { selected }) => (\n <EntityAutocompletePickerOption\n selected={selected}\n value={option}\n availableOptions={availableValues}\n showCounts={!!showCounts}\n />\n )}\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 {\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 { humanizeEntity, humanizeEntityRef } from '../EntityRefLink/humanize';\nimport { useFetchEntities } from './useFetchEntities';\nimport { withStyles } from '@material-ui/core/styles';\nimport { useEntityPresentation } from '../../apis';\nimport { catalogReactTranslationRef } from '../../translation';\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: { entity: Entity; isSelected: boolean }) {\n const classes = useStyles();\n const isGroup = props.entity.kind.toLocaleLowerCase('en-US') === 'group';\n const { primaryTitle: title } = useEntityPresentation(props.entity);\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 &nbsp;\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 {\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 const [selectedOwners, setSelectedOwners] = useState<string[]>(\n queryParamOwners.length ? queryParamOwners : filters.owners?.values ?? [],\n );\n\n const [{ value, loading }, handleFetch, cache] = useFetchEntities({\n mode,\n initialSelectedOwnersRefs: selectedOwners,\n });\n useDebouncedEffect(() => handleFetch({ text }), [text, handleFetch], 250);\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 (\n ['user', 'group'].includes(\n filters.kind?.value.toLocaleLowerCase('en-US') || '',\n )\n ) {\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 const entity =\n typeof o === 'string'\n ? cache.getEntity(o) ||\n parseEntityRef(o, {\n defaultKind: 'group',\n defaultNamespace: 'default',\n })\n : o;\n return humanizeEntity(entity, humanizeEntityRef(entity));\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 <RenderOptionLabel entity={entity} isSelected={selected} />;\n }}\n name=\"owner-picker\"\n onInputChange={(_e, inputValue) => {\n setText(inputValue);\n }}\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 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 { CompoundEntityRef, Entity } from '@backstage/catalog-model';\nimport Box from '@material-ui/core/Box';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport { Theme, makeStyles } from '@material-ui/core/styles';\nimport { useEntityPresentation } from '../../apis';\n\n/**\n * The available style class keys for {@link EntityDisplayName}, under the name\n * \"CatalogReactEntityDisplayName\".\n *\n * @public\n */\nexport type CatalogReactEntityDisplayNameClassKey = 'root' | 'icon';\n\nconst useStyles = makeStyles(\n (theme: Theme) => ({\n root: {\n display: 'inline-flex',\n alignItems: 'center',\n textDecoration: 'inherit',\n },\n icon: {\n marginRight: theme.spacing(0.5),\n color: theme.palette.text.secondary,\n '& svg': {\n verticalAlign: 'middle',\n },\n },\n }),\n { name: 'CatalogReactEntityDisplayName' },\n);\n\n/**\n * Props for {@link EntityDisplayName}.\n *\n * @public\n */\nexport type EntityDisplayNameProps = {\n entityRef: Entity | CompoundEntityRef | string;\n hideIcon?: boolean;\n disableTooltip?: boolean;\n defaultKind?: string;\n defaultNamespace?: string;\n};\n\n/**\n * Shows a nice representation of a reference to an entity.\n *\n * @public\n */\nexport const EntityDisplayName = (\n props: EntityDisplayNameProps,\n): JSX.Element => {\n const { entityRef, hideIcon, disableTooltip, defaultKind, defaultNamespace } =\n props;\n\n const classes = useStyles();\n const { primaryTitle, secondaryTitle, Icon } = useEntityPresentation(\n entityRef,\n { defaultKind, defaultNamespace },\n );\n\n // The innermost \"body\" content\n let content = <>{primaryTitle}</>;\n // Optionally an icon, and wrapper around them both\n content = (\n <Box component=\"span\" className={classes.root}>\n {Icon && !hideIcon ? (\n <Box component=\"span\" className={classes.icon}>\n <Icon fontSize=\"inherit\" />\n </Box>\n ) : null}\n {content}\n </Box>\n );\n\n // Optionally, a tooltip as the outermost layer\n if (secondaryTitle && !disableTooltip) {\n content = (\n <Tooltip enterDelay={1500} title={secondaryTitle}>\n {content}\n </Tooltip>\n );\n }\n\n return content;\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 { CompoundEntityRef, Entity } from '@backstage/catalog-model';\nimport { Link, LinkProps } from '@backstage/core-components';\nimport { useRouteRef } from '@backstage/core-plugin-api';\nimport { ReactNode, forwardRef } from 'react';\nimport { entityRouteParams, entityRouteRef } from '../../routes';\nimport { EntityDisplayName } from '../EntityDisplayName';\n\n/**\n * Props for {@link EntityRefLink}.\n *\n * @public\n */\nexport type EntityRefLinkProps = {\n entityRef: Entity | CompoundEntityRef | string;\n defaultKind?: string;\n defaultNamespace?: string;\n /** @deprecated This option should no longer be used; presentation is requested through the {@link entityPresentationApiRef} instead */\n title?: string;\n children?: ReactNode;\n hideIcon?: boolean;\n disableTooltip?: boolean;\n} & Omit<LinkProps, 'to'>;\n\n/**\n * Shows a clickable link to an entity.\n *\n * @public\n */\nexport const EntityRefLink = forwardRef<any, EntityRefLinkProps>(\n (props, ref) => {\n const {\n entityRef,\n defaultKind,\n defaultNamespace,\n title,\n children,\n hideIcon,\n disableTooltip,\n ...linkProps\n } = props;\n const entityRoute = useEntityRoute(props.entityRef);\n\n const content = children ?? title ?? (\n <EntityDisplayName\n entityRef={entityRef}\n defaultKind={defaultKind}\n defaultNamespace={defaultNamespace}\n hideIcon={hideIcon}\n disableTooltip={disableTooltip}\n />\n );\n\n return (\n <Link {...linkProps} ref={ref} to={entityRoute}>\n {content}\n </Link>\n );\n },\n) as (props: EntityRefLinkProps) => JSX.Element;\n\n// Hook that computes the route to a given entity / ref. This is a bit\n// contrived, because it tries to retain the casing of the entity name if\n// present, but not of other parts. This is in an attempt to make slightly more\n// nice-looking URLs.\nfunction useEntityRoute(\n entityRef: Entity | CompoundEntityRef | string,\n): string {\n const entityRoute = useRouteRef(entityRouteRef);\n\n const routeParams = entityRouteParams(entityRef, { encodeParams: true });\n\n return entityRoute(routeParams);\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 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 DEFAULT_NAMESPACE,\n} from '@backstage/catalog-model';\nimport get from 'lodash/get';\n\n/**\n * @param defaultNamespace - if set to false then namespace is never omitted,\n * if set to string which matches namespace of entity then omitted\n *\n * @public\n **/\nexport function humanizeEntityRef(\n entityRef: Entity | CompoundEntityRef,\n opts?: {\n defaultKind?: string;\n defaultNamespace?: string | false;\n },\n) {\n const defaultKind = opts?.defaultKind;\n let kind;\n let namespace;\n let name;\n\n if ('metadata' in entityRef) {\n kind = entityRef.kind;\n namespace = entityRef.metadata.namespace;\n name = entityRef.metadata.name;\n } else {\n kind = entityRef.kind;\n namespace = entityRef.namespace;\n name = entityRef.name;\n }\n\n if (namespace === undefined || namespace === '') {\n namespace = DEFAULT_NAMESPACE;\n }\n if (opts?.defaultNamespace !== undefined) {\n if (opts?.defaultNamespace === namespace) {\n namespace = undefined;\n }\n } else if (namespace === DEFAULT_NAMESPACE) {\n namespace = undefined;\n }\n\n kind = kind.toLocaleLowerCase('en-US');\n kind =\n defaultKind && defaultKind.toLocaleLowerCase('en-US') === kind\n ? undefined\n : kind;\n return `${kind ? `${kind}:` : ''}${namespace ? `${namespace}/` : ''}${name}`;\n}\n\n/**\n * Convert an entity to its more readable name if available.\n *\n * If an entity is either User or Group, this will be its `spec.profile.displayName`.\n * Otherwise, this is `metadata.title`.\n *\n * If neither of those are found or populated, fallback to `defaultName`.\n *\n * @param entity - Entity to convert.\n * @param defaultName - If entity readable name is not available, `defaultName` will be returned.\n * @returns Readable name, defaults to `defaultName`.\n *\n */\nexport function humanizeEntity(entity: Entity, defaultName: string) {\n for (const path of ['spec.profile.displayName', 'metadata.title']) {\n const value = get(entity, path);\n if (value && typeof value === 'string') {\n return value;\n }\n }\n return defaultName;\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: { kind: kindParameter, user: userParameter },\n } = useEntityList();\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 === undefined) {\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 constructor(readonly value: string, readonly label: string) {}\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 constructor(readonly value: string | string[]) {}\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 constructor(readonly values: string[]) {}\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 constructor(readonly value: string) {}\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 partialMatch = this.toUpperArray([\n entity.metadata.name,\n entity.metadata.title,\n (entity.spec?.profile as { displayName?: string })?.displayName,\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: ['metadata.name', 'metadata.title', 'spec.profile.displayName'],\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))\n .map(m => m.toLocaleUpperCase('en-US'));\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 constructor(readonly values: string[]) {}\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 constructor(readonly values: string[]) {}\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 private constructor(\n readonly value: UserListFilterKind,\n readonly refs?: string[],\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 constructor(\n readonly value: UserListFilterKind,\n readonly isOwnedEntity: (entity: Entity) => boolean,\n readonly isStarredEntity: (entity: Entity) => boolean,\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 constructor(readonly value: boolean) {}\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 constructor(readonly value: boolean) {}\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 constructor(readonly values: [string, 'asc' | 'desc'][]) {}\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 { compact, isEqual } from 'lodash';\nimport qs from 'qs';\nimport {\n createContext,\n PropsWithChildren,\n useCallback,\n useContext,\n useEffect,\n useMemo,\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 limit: number;\n offset?: number;\n setLimit: (limit: number) => void;\n setOffset?: (offset: number) => void;\n paginationMode: PaginationMode;\n};\n\n/**\n * Creates new context for entity listing and filtering.\n * @public\n */\nexport const EntityListContext = createContext<\n EntityListContextProps<any> | undefined\n>(undefined);\n\ntype OutputState<EntityFilters extends DefaultEntityFilters> = {\n appliedFilters: EntityFilters;\n appliedCursor?: string;\n entities: Entity[];\n backendEntities: Entity[];\n pageInfo?: QueryEntitiesResponse['pageInfo'];\n totalItems?: number;\n offset?: number;\n limit?: 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 const getPaginationMode = (): PaginationMode => {\n if (props.pagination === true) {\n return 'cursor';\n }\n return typeof props.pagination === 'object'\n ? props.pagination.mode ?? 'cursor'\n : 'none';\n };\n\n const paginationMode = getPaginationMode();\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 });\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 [outputState, setOutputState] = useState<OutputState<EntityFilters>>(\n () => {\n return {\n appliedFilters: {} as EntityFilters,\n entities: [],\n backendEntities: [],\n pageInfo: {},\n offset,\n limit,\n };\n },\n );\n\n // The main async filter worker. Note that while it has a lot of dependencies\n // in terms of its implementation, the triggering only happens (debounced)\n // based on the requested filters changing.\n const [{ value: resolvedValue, loading, error }, refresh] = useAsyncFn(\n async () => {\n const kindValue =\n requestedFilters.kind?.value?.toLocaleLowerCase('en-US');\n const adjustedFilters =\n kindValue === 'user' || kindValue === 'group'\n ? { ...requestedFilters, owners: undefined }\n : requestedFilters;\n const compacted = compact(Object.values(adjustedFilters));\n\n if (paginationMode !== 'none') {\n if (cursor) {\n if (cursor !== outputState.appliedCursor) {\n const entityFilter = reduceEntityFilters(compacted);\n const response = await catalogApi.queryEntities({\n cursor,\n limit,\n });\n return {\n appliedFilters: requestedFilters,\n appliedCursor: cursor,\n backendEntities: response.items,\n entities: response.items.filter(entityFilter),\n pageInfo: response.pageInfo,\n totalItems: response.totalItems,\n };\n }\n } else {\n const entityFilter = reduceEntityFilters(compacted);\n const backendFilter = reduceCatalogFilters(compacted);\n const previousBackendFilter = reduceCatalogFilters(\n compact(Object.values(outputState.appliedFilters)),\n );\n\n if (\n (paginationMode === 'offset' &&\n (outputState.limit !== limit || outputState.offset !== offset)) ||\n !isEqual(previousBackendFilter, backendFilter)\n ) {\n const response = await catalogApi.queryEntities({\n ...backendFilter,\n limit,\n offset,\n });\n return {\n appliedFilters: requestedFilters,\n backendEntities: response.items,\n entities: response.items.filter(entityFilter),\n pageInfo: response.pageInfo,\n totalItems: response.totalItems,\n limit,\n offset,\n };\n }\n }\n } else {\n const entityFilter = reduceEntityFilters(compacted);\n const backendFilter = reduceBackendCatalogFilters(compacted);\n const previousBackendFilter = reduceBackendCatalogFilters(\n compact(Object.values(outputState.appliedFilters)),\n );\n\n // TODO(mtlewis): currently entities will never be requested unless\n // there's at least one filter, we should allow an initial request\n // to happen with no filters.\n if (!isEqual(previousBackendFilter, backendFilter)) {\n // TODO(timbonicus): should limit fields here, but would need filter\n // fields + table columns\n const response = await catalogApi.getEntities({\n filter: backendFilter,\n });\n const entities = response.items.filter(entityFilter);\n return {\n appliedFilters: requestedFilters,\n backendEntities: response.items,\n entities,\n totalItems: entities.length,\n };\n }\n const entities = outputState.backendEntities.filter(entityFilter);\n return {\n appliedFilters: requestedFilters,\n backendEntities: outputState.backendEntities,\n entities,\n totalItems: entities.length,\n };\n }\n return undefined;\n },\n [\n catalogApi,\n queryParameters,\n requestedFilters,\n outputState,\n cursor,\n paginationMode,\n limit,\n offset,\n ],\n { loading: true },\n );\n\n // Slight debounce on the refresh, since (especially on page load) several\n // filters will be calling this in rapid succession.\n useDebounce(refresh, 10, [requestedFilters, cursor, limit, offset]);\n\n useEffect(() => {\n if (resolvedValue === undefined) {\n return;\n }\n setOutputState(resolvedValue);\n if (isMounted()) {\n const queryParams = Object.keys(requestedFilters).reduce(\n (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 },\n {} as Record<string, string | string[]>,\n );\n\n const oldParams = qs.parse(location.search, {\n ignoreQueryPrefix: true,\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 // We use direct history manipulation since useSearchParams and\n // useNavigate in react-router-dom cause unnecessary extra rerenders.\n // Also make sure to replace the state rather than pushing, since we\n // don't want there to be back/forward slots for every single filter\n // change.\n window.history?.replaceState(null, document.title, newUrl);\n }\n }, [\n cursor,\n isMounted,\n limit,\n location.search,\n offset,\n requestedFilters,\n resolvedValue,\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 pageInfo = useMemo(() => {\n if (paginationMode !== 'cursor') {\n return undefined;\n }\n\n const prevCursor = outputState.pageInfo?.prevCursor;\n const nextCursor = outputState.pageInfo?.nextCursor;\n return {\n prev: prevCursor ? () => setCursor(prevCursor) : undefined,\n next: nextCursor ? () => setCursor(nextCursor) : undefined,\n };\n }, [paginationMode, outputState.pageInfo]);\n\n const value = useMemo(\n () => ({\n filters: outputState.appliedFilters,\n entities: outputState.entities,\n backendEntities: outputState.backendEntities,\n updateFilters,\n queryParameters,\n loading,\n error,\n pageInfo,\n totalItems: outputState.totalItems,\n limit,\n offset,\n setLimit,\n setOffset,\n paginationMode,\n }),\n [\n outputState,\n updateFilters,\n queryParameters,\n loading,\n error,\n pageInfo,\n limit,\n offset,\n paginationMode,\n setLimit,\n setOffset,\n ],\n );\n\n return (\n <EntityListContext.Provider value={value}>\n {props.children}\n </EntityListContext.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 context = useContext(EntityListContext);\n if (!context)\n throw new Error('useEntityList must be used within EntityListProvider');\n return context;\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 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 DEFAULT_NAMESPACE,\n CompoundEntityRef,\n parseEntityRef,\n} from '@backstage/catalog-model';\nimport { createRouteRef } from '@backstage/core-plugin-api';\nimport { getOrCreateGlobalSingleton } from '@backstage/version-bridge';\n\n/**\n * A stable route ref that points to the catalog page for an individual entity.\n *\n * This `RouteRef` can be imported and used directly, and does not need to be referenced\n * via an `ExternalRouteRef`.\n *\n * If you want to replace the `EntityPage` from `@backstage/catalog-plugin` in your app,\n * you need to use the `entityRouteRef` as the mount point instead of your own.\n * @public\n */\nexport const entityRouteRef = getOrCreateGlobalSingleton(\n 'catalog:entity-route-ref',\n () =>\n createRouteRef({\n id: 'catalog:entity',\n params: ['namespace', 'kind', 'name'],\n }),\n);\n\n/**\n * Configurable options for `entityRouteParams`\n * @public\n */\nexport type EntityRouteParamsOptions = {\n encodeParams?: boolean;\n};\n\n/**\n * Utility function to get suitable route params for entityRoute, given an\n * @public\n */\nexport function entityRouteParams(\n entityOrRef: Entity | CompoundEntityRef | string,\n options?: EntityRouteParamsOptions,\n) {\n let kind;\n let namespace;\n let name;\n\n if (typeof entityOrRef === 'string') {\n const parsed = parseEntityRef(entityOrRef);\n kind = parsed.kind;\n namespace = parsed.namespace;\n name = parsed.name;\n } else if ('metadata' in entityOrRef) {\n kind = entityOrRef.kind;\n namespace = entityOrRef.metadata.namespace;\n name = entityOrRef.metadata.name;\n } else {\n kind = entityOrRef.kind;\n namespace = entityOrRef.namespace;\n name = entityOrRef.name;\n }\n\n kind = kind.toLocaleLowerCase('en-US');\n namespace = namespace?.toLocaleLowerCase('en-US') ?? DEFAULT_NAMESPACE;\n\n const { encodeParams = false } = options || {};\n if (encodeParams) {\n kind = encodeURIComponent(kind);\n namespace = encodeURIComponent(namespace);\n name = encodeURIComponent(name);\n }\n\n return {\n kind,\n namespace,\n name,\n } as const;\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 { createTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/** @alpha */\nexport const catalogReactTranslationRef = createTranslationRef({\n id: 'catalog-react',\n messages: {\n catalogFilter: {\n title: 'Filters',\n buttonTitle: 'Filters',\n },\n entityKindPicker: {\n title: 'Kind',\n errorMessage: 'Failed to load entity kinds',\n },\n entityLifecyclePicker: {\n title: 'Lifecycle',\n },\n entityNamespacePicker: {\n title: 'Namespace',\n },\n entityOwnerPicker: {\n title: 'Owner',\n },\n entityProcessingStatusPicker: {\n title: 'Processing Status',\n },\n entityTagPicker: {\n title: 'Tags',\n },\n entityPeekAheadPopover: {\n title: 'Drill into the entity to see all of the tags.',\n emailCardAction: {\n title: 'Email {{email}}',\n subTitle: 'mailto {{email}}',\n },\n entityCardActionsTitle: 'Show details',\n },\n entitySearchBar: {\n placeholder: 'Search',\n },\n entityTypePicker: {\n title: 'Type',\n errorMessage: 'Failed to load entity types',\n optionAllTitle: 'all',\n },\n favoriteEntity: {\n addToFavorites: 'Add to favorites',\n removeFromFavorites: 'Remove from favorites',\n },\n inspectEntityDialog: {\n title: 'Entity Inspector',\n closeButtonTitle: 'Close',\n ancestryPage: {\n title: 'Ancestry',\n },\n colocatedPage: {\n title: 'Colocated',\n description:\n 'These are the entities that are colocated with this entity - as in, they originated from the same data source (e.g. came from the same YAML file), or from the same origin (e.g. the originally registered URL).',\n alertNoLocation: 'Entity had no location information.',\n alertNoEntity: 'There were no other entities on this location.',\n },\n jsonPage: {\n title: 'Entity as JSON',\n description:\n 'This is the raw entity data as received from the catalog, on JSON form.',\n },\n overviewPage: {\n title: 'Overview',\n },\n yamlPage: {\n title: 'Entity as YAML',\n description:\n 'This is the raw entity data as received from the catalog, on YAML form.',\n },\n },\n unregisterEntityDialog: {\n title: 'Are you sure you want to unregister this entity?',\n cancelButtonTitle: 'Cancel',\n deleteButtonTitle: 'Delete Entity',\n deleteEntitySuccessMessage: 'Removed entity {{entityName}}',\n bootstrapState: {\n title:\n 'You cannot unregister this entity, since it originates from a protected Backstage configuration (location \"{{location}}\"). If you believe this is in error, please contact the {{appTitle}} integrator.',\n advancedDescription:\n 'You have the option to delete the entity itself from the catalog. Note that this should only be done if you know that the catalog file has been deleted at, or moved from, its origin location. If that is not the case, the entity will reappear shortly as the next refresh round is performed by the catalog.',\n advancedOptions: 'Advanced Options',\n },\n onlyDeleteStateTitle:\n 'This entity does not seem to originate from a registered location. You therefore only have the option to delete it outright from the catalog.',\n unregisterState: {\n title: 'This action will unregister the following entities:',\n subTitle: 'Located at the following location:',\n description: 'To undo, just re-register the entity in {{appTitle}}.',\n unregisterButtonTitle: 'Unregister Location',\n advancedOptions: 'Advanced Options',\n advancedDescription:\n 'You also have the option to delete the entity itself from the catalog. Note that this should only be done if you know that the catalog file has been deleted at, or moved from, its origin location. If that is not the case, the entity will reappear shortly as the next refresh round is performed by the catalog.',\n },\n errorStateTitle: 'Internal error: Unknown state',\n },\n userListPicker: {\n defaultOrgName: 'Company',\n personalFilter: {\n title: 'Personal',\n ownedLabel: 'Owned',\n starredLabel: 'Starred',\n },\n orgFilterAllLabel: 'All',\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 { 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 =>\n e.kind.toLocaleLowerCase('en-US') ===\n filter.kind.toLocaleLowerCase('en-US'),\n );\n }\n\n return entityNames;\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 ExternalRouteRef,\n routeRefType,\n AnyParams,\n ParamKeys,\n OptionalParams,\n} from './types';\n\n/**\n * @internal\n */\nexport class ExternalRouteRefImpl<\n Params extends AnyParams,\n Optional extends boolean,\n> implements ExternalRouteRef<Params, Optional>\n{\n // The marker is used for type checking while the symbol is used at runtime.\n declare $$routeRefType: 'external';\n readonly [routeRefType] = 'external';\n\n constructor(\n private readonly id: string,\n readonly params: ParamKeys<Params>,\n readonly optional: Optional,\n readonly defaultTarget: string | undefined,\n ) {}\n\n toString() {\n return `routeRef{type=external,id=${this.id}}`;\n }\n\n getDefaultTarget() {\n return this.defaultTarget;\n }\n}\n\n/**\n * Creates a route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @param options - Description of the route reference to be created.\n * @public\n */\nexport function createExternalRouteRef<\n Params extends { [param in ParamKey]: string },\n Optional extends boolean = false,\n ParamKey extends string = never,\n>(options: {\n /**\n * An identifier for this route, used to identify it in error messages\n */\n id: string;\n\n /**\n * The parameters that will be provided to the external route reference.\n */\n params?: ParamKey[];\n\n /**\n * Whether or not this route is optional, defaults to false.\n *\n * Optional external routes are not required to be bound in the app, and\n * if they aren't, `useRouteRef` will return `undefined`.\n */\n optional?: Optional;\n\n /**\n * The route (typically in another plugin) that this should map to by default.\n *\n * The string is expected to be on the standard `<plugin id>.<route id>` form,\n * for example `techdocs.docRoot`.\n */\n defaultTarget?: string;\n}): ExternalRouteRef<OptionalParams<Params>, Optional> {\n return new ExternalRouteRefImpl(\n options.id,\n (options.params ?? []) as ParamKeys<OptionalParams<Params>>,\n Boolean(options.optional) as Optional,\n options?.defaultTarget,\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 createExternalRouteRef,\n createRouteRef,\n} from '@backstage/core-plugin-api';\n\nexport const createComponentRouteRef = createExternalRouteRef({\n id: 'create-component',\n optional: true,\n defaultTarget: 'scaffolder.createComponent',\n});\n\nexport const viewTechDocRouteRef = createExternalRouteRef({\n id: 'view-techdoc',\n optional: true,\n params: ['namespace', 'kind', 'name'],\n defaultTarget: 'techdocs.docRoot',\n});\n\nexport const createFromTemplateRouteRef = createExternalRouteRef({\n id: 'create-from-template',\n optional: true,\n params: ['namespace', 'templateName'],\n defaultTarget: 'scaffolder.selectedTemplate',\n});\n\nexport const unregisterRedirectRouteRef = createExternalRouteRef({\n id: 'catalog:unregister-redirect',\n optional: true,\n});\n\nexport const rootRouteRef = createRouteRef({\n id: 'catalog',\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 AuthorizePermissionRequest,\n AuthorizePermissionResponse,\n DefinitivePolicyDecision,\n EvaluatorRequestOptions,\n Permission,\n PermissionAuthorizer,\n PermissionEvaluator,\n QueryPermissionRequest,\n QueryPermissionResponse,\n ResourcePermission,\n} from '../types';\n\n/**\n * Check if the two parameters are equivalent permissions.\n * @public\n */\nexport function isPermission<T extends Permission>(\n permission: Permission,\n comparedPermission: T,\n): permission is T {\n return permission.name === comparedPermission.name;\n}\n\n/**\n * Check if a given permission is a {@link ResourcePermission}. When\n * `resourceType` is supplied as the second parameter, also checks if\n * the permission has the specified resource type.\n * @public\n */\nexport function isResourcePermission<T extends string = string>(\n permission: Permission,\n resourceType?: T,\n): permission is ResourcePermission<T> {\n if (!('resourceType' in permission)) {\n return false;\n }\n\n return !resourceType || permission.resourceType === resourceType;\n}\n\n/**\n * Check if a given permission is related to a create action.\n * @public\n */\nexport function isCreatePermission(permission: Permission) {\n return permission.attributes.action === 'create';\n}\n\n/**\n * Check if a given permission is related to a read action.\n * @public\n */\nexport function isReadPermission(permission: Permission) {\n return permission.attributes.action === 'read';\n}\n\n/**\n * Check if a given permission is related to an update action.\n * @public\n */\nexport function isUpdatePermission(permission: Permission) {\n return permission.attributes.action === 'update';\n}\n\n/**\n * Check if a given permission is related to a delete action.\n * @public\n */\nexport function isDeletePermission(permission: Permission) {\n return permission.attributes.action === 'delete';\n}\n\n/**\n * Convert {@link PermissionAuthorizer} to {@link PermissionEvaluator}.\n *\n * @public\n */\nexport function toPermissionEvaluator(\n permissionAuthorizer: PermissionAuthorizer,\n): PermissionEvaluator {\n return {\n authorize: async (\n requests: AuthorizePermissionRequest[],\n options?: EvaluatorRequestOptions,\n ): Promise<AuthorizePermissionResponse[]> => {\n const response = await permissionAuthorizer.authorize(requests, options);\n\n return response as DefinitivePolicyDecision[];\n },\n authorizeConditional(\n requests: QueryPermissionRequest[],\n options?: EvaluatorRequestOptions,\n ): Promise<QueryPermissionResponse[]> {\n const parsedRequests =\n requests as unknown as AuthorizePermissionRequest[];\n return permissionAuthorizer.authorize(parsedRequests, options);\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 { JsonPrimitive } from '@backstage/types';\nimport { Permission, ResourcePermission } from './permission';\n\n/**\n * A request with a UUID identifier, so that batched responses can be matched up with the original\n * requests.\n * @public\n */\nexport type IdentifiedPermissionMessage<T> = T & { id: string };\n\n/**\n * A batch of request or response items.\n * @public\n */\nexport type PermissionMessageBatch<T> = {\n items: IdentifiedPermissionMessage<T>[];\n};\n\n/**\n * The result of an authorization request.\n * @public\n */\nexport enum AuthorizeResult {\n /**\n * The authorization request is denied.\n */\n DENY = 'DENY',\n /**\n * The authorization request is allowed.\n */\n ALLOW = 'ALLOW',\n /**\n * The authorization request is allowed if the provided conditions are met.\n */\n CONDITIONAL = 'CONDITIONAL',\n}\n\n/**\n * A definitive decision returned by the {@link @backstage/plugin-permission-node#PermissionPolicy}.\n *\n * @remarks\n *\n * This indicates that the policy unconditionally allows (or denies) the request.\n *\n * @public\n */\nexport type DefinitivePolicyDecision = {\n result: AuthorizeResult.ALLOW | AuthorizeResult.DENY;\n};\n\n/**\n * A conditional decision returned by the {@link @backstage/plugin-permission-node#PermissionPolicy}.\n *\n * @remarks\n *\n * This indicates that the policy allows authorization for the request, given that the returned\n * conditions hold when evaluated. The conditions will be evaluated by the corresponding plugin\n * which knows about the referenced permission rules.\n *\n * @public\n */\nexport type ConditionalPolicyDecision = {\n result: AuthorizeResult.CONDITIONAL;\n pluginId: string;\n resourceType: string;\n conditions: PermissionCriteria<PermissionCondition>;\n};\n\n/**\n * A decision returned by the {@link @backstage/plugin-permission-node#PermissionPolicy}.\n *\n * @public\n */\nexport type PolicyDecision =\n | DefinitivePolicyDecision\n | ConditionalPolicyDecision;\n\n/**\n * A condition returned with a CONDITIONAL authorization response.\n *\n * Conditions are a reference to a rule defined by a plugin, and parameters to apply the rule. For\n * example, a rule might be `isOwner` from the catalog-backend, and params may be a list of entity\n * claims from a identity token.\n * @public\n */\nexport type PermissionCondition<\n TResourceType extends string = string,\n TParams extends PermissionRuleParams = PermissionRuleParams,\n> = {\n resourceType: TResourceType;\n rule: string;\n params?: TParams;\n};\n\n/**\n * Utility type to represent an array with 1 or more elements.\n * @ignore\n */\ntype NonEmptyArray<T> = [T, ...T[]];\n\n/**\n * Represents a logical AND for the provided criteria.\n * @public\n */\nexport type AllOfCriteria<TQuery> = {\n allOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represents a logical OR for the provided criteria.\n * @public\n */\nexport type AnyOfCriteria<TQuery> = {\n anyOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represents a negation of the provided criteria.\n * @public\n */\nexport type NotCriteria<TQuery> = {\n not: PermissionCriteria<TQuery>;\n};\n\n/**\n * Composes several {@link PermissionCondition}s as criteria with a nested AND/OR structure.\n * @public\n */\nexport type PermissionCriteria<TQuery> =\n | AllOfCriteria<TQuery>\n | AnyOfCriteria<TQuery>\n | NotCriteria<TQuery>\n | TQuery;\n\n/**\n * A parameter to a permission rule.\n *\n * @public\n */\nexport type PermissionRuleParam = undefined | JsonPrimitive | JsonPrimitive[];\n\n/**\n * Types that can be used as parameters to permission rules.\n *\n * @public\n */\nexport type PermissionRuleParams =\n | undefined\n | Record<string, PermissionRuleParam>;\n\n/**\n * An individual request sent to the permission backend.\n * @public\n */\nexport type EvaluatePermissionRequest = {\n permission: Permission;\n resourceRef?: string;\n};\n\n/**\n * A batch of requests sent to the permission backend.\n * @public\n * @deprecated This type is not used and it will be removed in the future\n */\nexport type EvaluatePermissionRequestBatch =\n PermissionMessageBatch<EvaluatePermissionRequest>;\n\n/**\n * An individual response from the permission backend.\n *\n * @remarks\n *\n * This response type is an alias of {@link PolicyDecision} to maintain separation between the\n * {@link @backstage/plugin-permission-node#PermissionPolicy} interface and the permission backend\n * api. They may diverge at some point in the future. The response\n *\n * @public\n */\nexport type EvaluatePermissionResponse = PolicyDecision;\n\n/**\n * A batch of responses from the permission backend.\n * @public\n */\nexport type EvaluatePermissionResponseBatch =\n PermissionMessageBatch<EvaluatePermissionResponse>;\n\n/**\n * Request object for {@link PermissionEvaluator.authorize}. If a {@link ResourcePermission}\n * is provided, it must include a corresponding `resourceRef`.\n * @public\n */\nexport type AuthorizePermissionRequest =\n | {\n permission: Exclude<Permission, ResourcePermission>;\n resourceRef?: never;\n }\n | { permission: ResourcePermission; resourceRef: string };\n\n/**\n * Response object for {@link PermissionEvaluator.authorize}.\n * @public\n */\nexport type AuthorizePermissionResponse = DefinitivePolicyDecision;\n\n/**\n * Request object for {@link PermissionEvaluator.authorizeConditional}.\n * @public\n */\nexport type QueryPermissionRequest = {\n permission: ResourcePermission;\n resourceRef?: never;\n};\n\n/**\n * Response object for {@link PermissionEvaluator.authorizeConditional}.\n * @public\n */\nexport type QueryPermissionResponse = PolicyDecision;\n\n/**\n * A client interacting with the permission backend can implement this evaluator interface.\n *\n * @public\n */\nexport interface PermissionEvaluator {\n /**\n * Evaluates {@link Permission | Permissions} and returns a definitive decision.\n */\n authorize(\n requests: AuthorizePermissionRequest[],\n options?: EvaluatorRequestOptions & { _ignored?: never }, // Since the options are empty we add this placeholder to reject all options\n ): Promise<AuthorizePermissionResponse[]>;\n\n /**\n * Evaluates {@link ResourcePermission | ResourcePermissions} and returns both definitive and\n * conditional decisions, depending on the configured\n * {@link @backstage/plugin-permission-node#PermissionPolicy}. This method is useful when the\n * caller needs more control over the processing of conditional decisions. For example, a plugin\n * backend may want to use {@link PermissionCriteria | conditions} in a database query instead of\n * evaluating each resource in memory.\n */\n authorizeConditional(\n requests: QueryPermissionRequest[],\n options?: EvaluatorRequestOptions & { _ignored?: never }, // Since the options are empty we add this placeholder to reject all options\n ): Promise<QueryPermissionResponse[]>;\n}\n\n// Note(Rugvip): I kept the below type around in case we want to add new options\n// in the future, for example a signal. It also helps out enabling API\n// constraints, as without this we can't have the permissions service implement\n// the evaluator interface due to the mismatch in parameter count.\n\n/**\n * Options for {@link PermissionEvaluator} requests.\n *\n * This is currently empty, as there are no longer any common options for the permission evaluator.\n *\n * @public\n */\nexport interface EvaluatorRequestOptions {}\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 EvaluatePermissionRequest,\n EvaluatePermissionResponse,\n} from '@backstage/plugin-permission-common';\nimport { ApiRef, createApiRef } from '@backstage/core-plugin-api';\n\n/**\n * This API is used by various frontend utilities that allow developers to implement authorization within their frontend\n * plugins. A plugin developer will likely not have to interact with this API or its implementations directly, but\n * rather with the aforementioned utility components/hooks.\n * @public\n */\nexport type PermissionApi = {\n authorize(\n request: EvaluatePermissionRequest,\n ): Promise<EvaluatePermissionResponse>;\n};\n\n/**\n * A Backstage ApiRef for the Permission API. See https://backstage.io/docs/api/utility-apis for more information on\n * Backstage ApiRefs.\n * @public\n */\nexport const permissionApiRef: ApiRef<PermissionApi> = createApiRef({\n id: 'plugin.permission.api',\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 */\n\nimport { useMemo } from 'react';\nimport { makeStyles } from '@material-ui/core/styles';\n\n/** @public */\nexport type HighlightedSearchResultTextClassKey = 'highlight';\n\nconst useStyles = makeStyles(\n () => ({\n highlight: {},\n }),\n { name: 'BackstageHighlightedSearchResultText' },\n);\n\n/**\n * Props for {@link HighlightedSearchResultText}.\n *\n * @public\n */\nexport type HighlightedSearchResultTextProps = {\n text: string;\n preTag: string;\n postTag: string;\n};\n\n/**\n * @public\n */\nexport const HighlightedSearchResultText = (\n props: HighlightedSearchResultTextProps,\n) => {\n const { text, preTag, postTag } = props;\n\n const classes = useStyles();\n const terms = useMemo(\n () => text.split(new RegExp(`(${preTag}.+?${postTag})`)),\n [postTag, preTag, text],\n );\n\n return (\n <>\n {terms.map((t, idx) =>\n t.includes(preTag) ? (\n <mark className={classes.highlight} key={idx}>\n {t.replace(new RegExp(`${preTag}|${postTag}`, 'g'), '')}\n </mark>\n ) : (\n t\n ),\n )}\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 */\n\nimport {\n Fragment,\n ReactNode,\n PropsWithChildren,\n isValidElement,\n createElement,\n cloneElement,\n useCallback,\n} from 'react';\n\nimport {\n getComponentData,\n useElementFilter,\n Extension,\n createReactExtension,\n useAnalytics,\n} from '@backstage/core-plugin-api';\nimport { SearchDocument, SearchResult } from '@backstage/plugin-search-common';\n\nimport List, { ListProps } from '@material-ui/core/List';\nimport ListItem, { ListItemProps } from '@material-ui/core/ListItem';\n\nimport { DefaultResultListItem } from './components/DefaultResultListItem';\n\n/**\n * @internal\n * Key for result extensions.\n */\nconst SEARCH_RESULT_LIST_ITEM_EXTENSION =\n 'search.results.list.items.extensions.v1';\n\n/**\n * @internal\n * Returns the first extension element found for a given result, and null otherwise.\n * @param elements - All extension elements.\n * @param result - The search result.\n */\nconst findSearchResultListItemExtensionElement = (\n elements: ReactNode[],\n result: SearchResult,\n) => {\n for (const element of elements) {\n if (!isValidElement(element)) continue;\n const predicate = getComponentData<(result: SearchResult) => boolean>(\n element,\n SEARCH_RESULT_LIST_ITEM_EXTENSION,\n );\n if (!predicate?.(result)) continue;\n return cloneElement(element, {\n rank: result.rank,\n highlight: result.highlight,\n result: result.document,\n // Use props in situations where a consumer is manually rendering the extension\n ...element.props,\n });\n }\n return null;\n};\n\n/**\n * @public\n * Extends props for any search result list item extension\n */\nexport type SearchResultListItemExtensionProps<Props extends {} = {}> = Props &\n PropsWithChildren<\n {\n rank?: number;\n result?: SearchDocument;\n noTrack?: boolean;\n } & Omit<ListItemProps, 'button'>\n >;\n\n/**\n * @internal\n * Extends children with extension capabilities.\n * @param props - see {@link SearchResultListItemExtensionProps}.\n */\nexport const SearchResultListItemExtension = (\n props: SearchResultListItemExtensionProps,\n) => {\n const {\n rank,\n result,\n noTrack,\n children,\n alignItems = 'flex-start',\n ...rest\n } = props;\n const analytics = useAnalytics();\n\n const handleClickCapture = useCallback(() => {\n if (noTrack) return;\n if (!result) return;\n analytics.captureEvent('discover', result.title, {\n attributes: { to: result.location },\n value: rank,\n });\n }, [rank, result, noTrack, analytics]);\n\n return (\n <ListItem\n divider\n alignItems={alignItems}\n onClickCapture={handleClickCapture}\n {...rest}\n >\n {children}\n </ListItem>\n );\n};\n\n/**\n * @public\n * Options for {@link createSearchResultListItemExtension}.\n */\nexport type SearchResultListItemExtensionOptions<\n Component extends (props: any) => JSX.Element | null,\n> = {\n /**\n * The extension name.\n */\n name: string;\n /**\n * The extension component.\n */\n component: () => Promise<Component>;\n /**\n * When an extension defines a predicate, it returns true if the result should be rendered by that extension.\n * Defaults to a predicate that returns true, which means it renders all sorts of results.\n */\n predicate?: (result: SearchResult) => boolean;\n};\n\n/**\n * @public\n * Creates a search result item extension.\n * @param options - The extension options, see {@link SearchResultListItemExtensionOptions} for more details.\n */\nexport const createSearchResultListItemExtension = <\n Component extends (props: any) => JSX.Element | null,\n>(\n options: SearchResultListItemExtensionOptions<Component>,\n): Extension<Component> => {\n const { name, component, predicate = () => true } = options;\n\n return createReactExtension<Component>({\n name,\n component: {\n lazy: () =>\n component().then(\n type =>\n (props => (\n <SearchResultListItemExtension\n rank={props.rank}\n result={props.result}\n noTrack={props.noTrack}\n >\n {createElement(type, props)}\n </SearchResultListItemExtension>\n )) as Component,\n ),\n },\n data: {\n [SEARCH_RESULT_LIST_ITEM_EXTENSION]: predicate,\n },\n });\n};\n\n/**\n * @public\n * Returns a function that renders a result using extensions.\n */\nexport const useSearchResultListItemExtensions = (children: ReactNode) => {\n const elements = useElementFilter(\n children,\n collection => {\n return collection\n .selectByComponentData({\n key: SEARCH_RESULT_LIST_ITEM_EXTENSION,\n })\n .getElements();\n },\n [children],\n );\n\n return useCallback(\n (result: SearchResult, key?: number) => {\n const element = findSearchResultListItemExtensionElement(\n elements,\n result,\n );\n\n return (\n <Fragment key={key}>\n {element ?? (\n <SearchResultListItemExtension\n rank={result.rank}\n result={result.document}\n >\n <DefaultResultListItem\n rank={result.rank}\n highlight={result.highlight}\n result={result.document}\n />\n </SearchResultListItemExtension>\n )}\n </Fragment>\n );\n },\n [elements],\n );\n};\n\n/**\n * @public\n * Props for {@link SearchResultListItemExtensions}\n */\nexport type SearchResultListItemExtensionsProps = Omit<ListProps, 'results'> & {\n /**\n * Search result list.\n */\n results: SearchResult[];\n};\n\n/**\n * @public\n * Render results using search extensions.\n * @param props - see {@link SearchResultListItemExtensionsProps}\n */\nexport const SearchResultListItemExtensions = (\n props: SearchResultListItemExtensionsProps,\n) => {\n const { results, children, ...rest } = props;\n const render = useSearchResultListItemExtensions(children);\n return <List {...rest}>{results.map(render)}</List>;\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\n/** @public */\nexport const TECHDOCS_ANNOTATION = 'backstage.io/techdocs-ref';\n/** @public */\nexport const TECHDOCS_EXTERNAL_ANNOTATION = 'backstage.io/techdocs-entity';\n/** @public */\nexport const TECHDOCS_EXTERNAL_PATH_ANNOTATION =\n 'backstage.io/techdocs-entity-path';\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 */\n\nimport { PropsWithChildren, ComponentType, useCallback } from 'react';\nimport { useOutlet } from 'react-router-dom';\n\nimport {\n attachComponentData,\n createReactExtension,\n ElementCollection,\n Extension,\n useElementFilter,\n} from '@backstage/core-plugin-api';\n\nimport { TechDocsAddonLocations, TechDocsAddonOptions } from './types';\n\n/**\n * Key for each addon.\n * @public\n */\nexport const TECHDOCS_ADDONS_KEY = 'techdocs.addons.addon.v1';\n\n/**\n * Marks the `<TechDocsAddons>` registry component.\n * @public\n */\nexport const TECHDOCS_ADDONS_WRAPPER_KEY = 'techdocs.addons.wrapper.v1';\n\n/**\n * TechDocs Addon registry.\n * @public\n */\nexport const TechDocsAddons: ComponentType<PropsWithChildren<{}>> = () => null;\n\nattachComponentData(TechDocsAddons, TECHDOCS_ADDONS_WRAPPER_KEY, true);\n\nexport const getDataKeyByName = (name: string) => {\n return `${TECHDOCS_ADDONS_KEY}.${name.toLocaleLowerCase('en-US')}`;\n};\n\n/**\n * Create a TechDocs addon overload signature without props.\n * @public\n */\nexport function createTechDocsAddonExtension(\n options: TechDocsAddonOptions,\n): Extension<() => JSX.Element | null>;\n\n/**\n * Create a TechDocs addon overload signature with props.\n * @public\n */\nexport function createTechDocsAddonExtension<TComponentProps>(\n options: TechDocsAddonOptions<TComponentProps>,\n): Extension<(props: TComponentProps) => JSX.Element | null>;\n\n/**\n * Create a TechDocs addon implementation.\n * @public\n */\nexport function createTechDocsAddonExtension<\n TComponentProps extends PropsWithChildren<{}>,\n>(\n options: TechDocsAddonOptions<TComponentProps>,\n): Extension<(props: TComponentProps) => JSX.Element | null> {\n const { name, component: TechDocsAddon } = options;\n return createReactExtension({\n name,\n component: {\n sync: (props: TComponentProps) => <TechDocsAddon {...props} />,\n },\n data: {\n [TECHDOCS_ADDONS_KEY]: options,\n [getDataKeyByName(name)]: true,\n },\n });\n}\n\nconst getTechDocsAddonByName = (\n collection: ElementCollection,\n key: string,\n): JSX.Element | undefined => {\n return collection.selectByComponentData({ key }).getElements()[0];\n};\n\nconst getAllTechDocsAddons = (collection: ElementCollection) => {\n return collection\n .selectByComponentData({\n key: TECHDOCS_ADDONS_WRAPPER_KEY,\n })\n .selectByComponentData({\n key: TECHDOCS_ADDONS_KEY,\n });\n};\n\nconst getAllTechDocsAddonsData = (collection: ElementCollection) => {\n return collection\n .selectByComponentData({\n key: TECHDOCS_ADDONS_WRAPPER_KEY,\n })\n .findComponentData<TechDocsAddonOptions>({\n key: TECHDOCS_ADDONS_KEY,\n });\n};\n\n/**\n * hook to use addons in components\n * @public\n */\nexport const useTechDocsAddons = () => {\n const node = useOutlet();\n const collection = useElementFilter(node, getAllTechDocsAddons);\n const options = useElementFilter(node, getAllTechDocsAddonsData);\n\n const findAddonByData = useCallback(\n (data: TechDocsAddonOptions | undefined) => {\n if (!collection || !data) return null;\n const nameKey = getDataKeyByName(data.name);\n return getTechDocsAddonByName(collection, nameKey) ?? null;\n },\n [collection],\n );\n\n const renderComponentByName = useCallback(\n (name: string) => {\n const data = options.find(option => option.name === name);\n return data ? findAddonByData(data) : null;\n },\n [options, findAddonByData],\n );\n\n const renderComponentsByLocation = useCallback(\n (location: keyof typeof TechDocsAddonLocations) => {\n const data = options.filter(option => option.location === location);\n return data.length ? data.map(findAddonByData) : null;\n },\n [options, findAddonByData],\n );\n\n return { renderComponentByName, renderComponentsByLocation };\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 */\n\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport { createApiRef } from '@backstage/core-plugin-api';\nimport { TechDocsEntityMetadata, TechDocsMetadata } from './types';\n\n/**\n * API to talk to techdocs-backend.\n *\n * @public\n */\nexport interface TechDocsApi {\n getCookie(): Promise<{ expiresAt: string }>;\n getApiOrigin(): Promise<string>;\n getTechDocsMetadata(entityId: CompoundEntityRef): Promise<TechDocsMetadata>;\n getEntityMetadata(\n entityId: CompoundEntityRef,\n ): Promise<TechDocsEntityMetadata>;\n}\n\n/**\n * Utility API reference for the {@link TechDocsApi}.\n *\n * @public\n */\nexport const techdocsApiRef = createApiRef<TechDocsApi>({\n id: 'plugin.techdocs.service',\n});\n\n/**\n * The outcome of a docs sync operation.\n *\n * @public\n */\nexport type SyncResult = 'cached' | 'updated';\n\n/**\n * API which talks to TechDocs storage to fetch files to render.\n *\n * @public\n */\nexport interface TechDocsStorageApi {\n getApiOrigin(): Promise<string>;\n getStorageUrl(): Promise<string>;\n getBuilder(): Promise<string>;\n getEntityDocs(entityId: CompoundEntityRef, path: string): Promise<string>;\n syncEntityDocs(\n entityId: CompoundEntityRef,\n logHandler?: (line: string) => void,\n ): Promise<SyncResult>;\n getBaseUrl(\n oldBaseUrl: string,\n entityId: CompoundEntityRef,\n path: string,\n ): Promise<string>;\n}\n\n/**\n * Utility API reference for the {@link TechDocsStorageApi}.\n *\n * @public\n */\nexport const techdocsStorageApiRef = createApiRef<TechDocsStorageApi>({\n id: 'plugin.techdocs.storageservice',\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 */\n\nimport {\n Dispatch,\n SetStateAction,\n useContext,\n useState,\n memo,\n ReactNode,\n useEffect,\n} from 'react';\nimport useAsync, { AsyncState } from 'react-use/esm/useAsync';\nimport useAsyncRetry from 'react-use/esm/useAsyncRetry';\n\nimport {\n CompoundEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport {\n createVersionedContext,\n createVersionedValueMap,\n} from '@backstage/version-bridge';\n\nimport {\n AnalyticsContext,\n configApiRef,\n useApi,\n} from '@backstage/core-plugin-api';\n\nimport { techdocsApiRef } from './api';\nimport { TechDocsEntityMetadata, TechDocsMetadata } from './types';\n\nimport { toLowercaseEntityRefMaybe } from './helpers';\n\nconst areEntityRefsEqual = (\n prevEntityRef: CompoundEntityRef,\n nextEntityRef: CompoundEntityRef,\n) => {\n return (\n stringifyEntityRef(prevEntityRef) === stringifyEntityRef(nextEntityRef)\n );\n};\n\n/**\n * @public type for the value of the TechDocsReaderPageContext\n */\nexport type TechDocsReaderPageValue = {\n metadata: AsyncState<TechDocsMetadata>;\n entityRef: CompoundEntityRef;\n entityMetadata: AsyncState<TechDocsEntityMetadata>;\n shadowRoot?: ShadowRoot;\n setShadowRoot: Dispatch<SetStateAction<ShadowRoot | undefined>>;\n title: string;\n setTitle: Dispatch<SetStateAction<string>>;\n subtitle: string;\n setSubtitle: Dispatch<SetStateAction<string>>;\n /**\n * @deprecated property can be passed down directly to the `TechDocsReaderPageContent` instead.\n */\n onReady?: () => void;\n};\n\nconst defaultTechDocsReaderPageValue: TechDocsReaderPageValue = {\n title: '',\n subtitle: '',\n setTitle: () => {},\n setSubtitle: () => {},\n setShadowRoot: () => {},\n metadata: { loading: true },\n entityMetadata: { loading: true },\n entityRef: { kind: '', name: '', namespace: '' },\n};\n\nconst TechDocsReaderPageContext = createVersionedContext<{\n 1: TechDocsReaderPageValue;\n}>('techdocs-reader-page-context');\n\n/**\n * render function for {@link TechDocsReaderPageProvider}\n *\n * @public\n */\nexport type TechDocsReaderPageProviderRenderFunction = (\n value: TechDocsReaderPageValue,\n) => JSX.Element;\n\n/**\n * Props for {@link TechDocsReaderPageProvider}\n *\n * @public\n */\nexport type TechDocsReaderPageProviderProps = {\n entityRef: CompoundEntityRef;\n children: TechDocsReaderPageProviderRenderFunction | ReactNode;\n};\n\n/**\n * A context to store the reader page state\n * @public\n */\nexport const TechDocsReaderPageProvider = memo(\n (props: TechDocsReaderPageProviderProps) => {\n const { entityRef, children } = props;\n\n const techdocsApi = useApi(techdocsApiRef);\n const config = useApi(configApiRef);\n\n const entityMetadata = useAsync(async () => {\n return techdocsApi.getEntityMetadata(entityRef);\n }, [entityRef]);\n\n const metadata = useAsyncRetry(async () => {\n return techdocsApi.getTechDocsMetadata(entityRef);\n }, [entityRef]);\n\n const [title, setTitle] = useState(defaultTechDocsReaderPageValue.title);\n const [subtitle, setSubtitle] = useState(\n defaultTechDocsReaderPageValue.subtitle,\n );\n const [shadowRoot, setShadowRoot] = useState<ShadowRoot | undefined>(\n defaultTechDocsReaderPageValue.shadowRoot,\n );\n\n useEffect(() => {\n if (shadowRoot && !metadata.value && !metadata.loading) {\n metadata.retry();\n }\n }, [\n metadata.value,\n metadata.loading,\n shadowRoot,\n metadata.retry,\n metadata,\n ]);\n\n const value: TechDocsReaderPageValue = {\n metadata,\n entityRef: toLowercaseEntityRefMaybe(entityRef, config),\n entityMetadata,\n shadowRoot,\n setShadowRoot,\n title,\n setTitle,\n subtitle,\n setSubtitle,\n };\n const versionedValue = createVersionedValueMap({ 1: value });\n\n return (\n <AnalyticsContext\n attributes={{ entityRef: stringifyEntityRef(entityRef) }}\n >\n <TechDocsReaderPageContext.Provider value={versionedValue}>\n {children instanceof Function ? children(value) : children}\n </TechDocsReaderPageContext.Provider>\n </AnalyticsContext>\n );\n },\n (prevProps, nextProps) => {\n return areEntityRefsEqual(prevProps.entityRef, nextProps.entityRef);\n },\n);\n\n/**\n * Hook used to get access to shared state between reader page components.\n * @public\n */\nexport const useTechDocsReaderPage = () => {\n const versionedContext = useContext(TechDocsReaderPageContext);\n\n if (versionedContext === undefined) {\n return defaultTechDocsReaderPageValue;\n }\n\n const context = versionedContext.atVersion(1);\n if (context === undefined) {\n throw new Error('No context found for version 1.');\n }\n\n return context;\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 */\n\nimport { Config } from '@backstage/config';\nimport {\n CompoundEntityRef,\n Entity,\n getCompoundEntityRef,\n parseEntityRef,\n} from '@backstage/catalog-model';\nimport {\n TECHDOCS_EXTERNAL_ANNOTATION,\n TECHDOCS_EXTERNAL_PATH_ANNOTATION,\n} from '@backstage/plugin-techdocs-common';\nimport { RouteFunc } from '@backstage/core-plugin-api';\n\n/**\n * Lower-case entity triplets by default, but allow override.\n *\n * @public\n */\nexport function toLowercaseEntityRefMaybe(\n entityRef: CompoundEntityRef,\n config: Config,\n): CompoundEntityRef {\n if (config.getOptionalBoolean('techdocs.legacyUseCaseSensitiveTripletPaths'))\n return entityRef;\n\n entityRef.kind = entityRef.kind.toLocaleLowerCase();\n entityRef.name = entityRef.name.toLocaleLowerCase();\n entityRef.namespace = entityRef.namespace.toLocaleLowerCase();\n\n return entityRef;\n}\n\n/**\n * Get the entity path annotation from the given entity and ensure it starts with a slash.\n *\n * @public\n */\nexport function getEntityRootTechDocsPath(entity: Entity): string {\n let path = entity.metadata.annotations?.[TECHDOCS_EXTERNAL_PATH_ANNOTATION];\n if (!path) {\n return '';\n }\n if (!path.startsWith('/')) {\n path = `/${path}`;\n }\n return path;\n}\n\n/**\n * Build the TechDocs URL for the given entity. This helper should be used anywhere there\n * is a link to an entities TechDocs.\n *\n * @public\n */\nexport const buildTechDocsURL = (\n entity: Entity,\n routeFunc:\n | RouteFunc<{\n namespace: string;\n kind: string;\n name: string;\n }>\n | undefined,\n) => {\n if (!routeFunc) {\n return undefined;\n }\n\n let { namespace, kind, name } = getCompoundEntityRef(entity);\n\n if (entity.metadata.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION]) {\n try {\n const techdocsRef = parseEntityRef(\n entity.metadata.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION],\n );\n namespace = techdocsRef.namespace;\n kind = techdocsRef.kind;\n name = techdocsRef.name;\n } catch {\n // not a fan of this but we don't care if the parseEntityRef fails\n }\n }\n\n const url = routeFunc({\n namespace,\n kind,\n name,\n });\n\n // Add on the external entity path to the url if one exists. This allows deep linking into another\n // entities TechDocs.\n const path = getEntityRootTechDocsPath(entity);\n\n return `${url}${path}`;\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 */\n\nimport { ComponentType } from 'react';\nimport { Entity } from '@backstage/catalog-model';\n\n/**\n * Metadata for TechDocs page\n *\n * @public\n */\nexport type TechDocsMetadata = {\n site_name: string;\n site_description: string;\n};\n\n/**\n * Metadata for TechDocs Entity\n *\n * @public\n */\nexport type TechDocsEntityMetadata = Entity & {\n locationMetadata?: { type: string; target: string };\n};\n\n/**\n * Locations for which TechDocs addons may be declared and rendered.\n * @public\n */\nexport const TechDocsAddonLocations = Object.freeze({\n /**\n * These addons fill up the header from the right, on the same line as the\n * title.\n */\n Header: 'Header',\n\n /**\n * These addons appear below the header and above all content; tooling addons\n * can be inserted for convenience.\n */\n Subheader: 'Subheader',\n\n /**\n * These addons are items added to the settings menu list and are designed to make\n * the reader experience customizable, for example accessibility options\n */\n Settings: 'Settings',\n\n /**\n * These addons appear left of the content and above the navigation.\n */\n PrimarySidebar: 'PrimarySidebar',\n\n /**\n * These addons appear right of the content and above the table of contents.\n */\n SecondarySidebar: 'SecondarySidebar',\n\n /**\n * A virtual location which allows mutation of all content within the shadow\n * root by transforming DOM nodes. These addons should return null on render.\n */\n Content: 'Content',\n\n /**\n * todo(backstage/community): This is a proposed virtual location which would\n * help implement a common addon pattern in which many instances of a given\n * element in markdown would be dynamically replaced at render-time based on\n * attributes provided on that element, for example:\n *\n * ```md\n * ## For Fun\n * <TechDocsAddon>CatGif</TechDocsAddon>\n *\n * ## Component Metadata\n * <TechDocsAddon entityRef=\"default:component/some-component-name\">CatalogEntityCard</TechDocsAddon>\n *\n * ## System Metadata\n * <TechDocsAddon entityRef=\"default:system/some-system-name\">CatalogEntityCard</TechDocsAddon>\n * ```\n *\n * Could correspond to a TechDocs addon named `CatalogEntityCard` with\n * location `TechDocsAddonLocations.COMPONENT`, whose `component` would be\n * the react component that would be rendered in place of all instances of\n * the markdown illustrated above.\n *\n * The `@backstage/plugin-techdocs-react` package would need to be updated to, in\n * cases where such addons had been registered, find all instances of the\n * the `<TechDocsAddon>` tag whose `textContent` corresponded with the name of the\n * addon, then replace them with component instances of the addon component,\n * passing any attributes from the tag as props to the component.\n */\n // Component: 'Component',\n} as const);\n\n/**\n * Options for creating a TechDocs addon.\n * @public\n */\nexport type TechDocsAddonOptions<TAddonProps = {}> = {\n name: string;\n location: keyof typeof TechDocsAddonLocations;\n component: ComponentType<TAddonProps>;\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.toLocaleLowerCase('en-US');\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","/*\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 { 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 } = props;\n const { updateFilters, setLimit, setOffset, limit, totalItems, offset } =\n useEntityList();\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 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={{ pagination: { labelDisplayedRows: '' } }}\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 { 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\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={{ pagination: { labelDisplayedRows: '' } }}\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 { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport {\n useEntityList,\n useStarredEntities,\n} from '@backstage/plugin-catalog-react';\nimport { DocsTable } from './DocsTable';\nimport { OffsetPaginatedDocsTable } from './OffsetPaginatedDocsTable';\nimport { CursorPaginatedDocsTable } from './CursorPaginatedDocsTable';\nimport { actionFactories } from './actions';\nimport { columnFactories, defaultColumns } from './columns';\nimport { DocsTableRow } 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 */\nexport const EntityListDocsTable = (props: EntityListDocsTableProps) => {\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\n const title = capitalize(filters.user?.value ?? 'all');\n\n const defaultActions = [\n actionFactories.createCopyDocsUrlAction(copyToClipboard),\n actionFactories.createStarEntityAction(\n isStarredEntity,\n toggleStarredEntity,\n ),\n ];\n\n const documents = entitiesToDocsMapper(\n entities,\n getRouteToReaderPageFor,\n config,\n );\n\n if (paginationMode === 'cursor') {\n return (\n <CursorPaginatedDocsTable\n columns={columns || defaultColumns}\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={columns || defaultColumns}\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\n severity=\"error\"\n title=\"Could not load available documentation.\"\n >\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={columns}\n options={options}\n />\n );\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 { ReactNode, FC } from 'react';\nimport {\n Content,\n ContentHeader,\n SupportButton,\n} from '@backstage/core-components';\nimport {\n CatalogFilterLayout,\n EntityListProvider,\n EntityOwnerPicker,\n EntityTagPicker,\n UserListPicker,\n} from '@backstage/plugin-catalog-react';\nimport { TechDocsPageWrapper } from './TechDocsPageWrapper';\nimport { TechDocsPicker } from './TechDocsPicker';\nimport { EntityListDocsTable } from './Tables';\nimport { TechDocsIndexPageProps } from './TechDocsIndexPage';\n\n/**\n * Props for {@link DefaultTechDocsHome}\n *\n * @public\n * @deprecated Please use `TechDocsIndexPageProps` instead.\n */\nexport type DefaultTechDocsHomeProps = TechDocsIndexPageProps;\n\n/**\n * Component which renders a default documentation landing page.\n *\n * @public\n */\nexport const DefaultTechDocsHome = (props: TechDocsIndexPageProps) => {\n const {\n initialFilter = 'owned',\n columns,\n actions,\n ownerPickerMode,\n pagination,\n options,\n PageWrapper,\n CustomHeader,\n } = props;\n const Wrapper: FC<{\n children: ReactNode;\n }> = PageWrapper ? PageWrapper : TechDocsPageWrapper;\n const Header: FC =\n CustomHeader ||\n (() => (\n <ContentHeader title=\"\">\n <SupportButton>Discover documentation in your ecosystem.</SupportButton>\n </ContentHeader>\n ));\n return (\n <Wrapper>\n <Content>\n <Header />\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 </Content>\n </Wrapper>\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';\n\nimport { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport { Entity } from '@backstage/catalog-model';\nimport { rootDocsRouteRef } from '../../../routes';\nimport {\n EmptyState,\n LinkButton,\n Table,\n TableColumn,\n TableOptions,\n TableProps,\n} from '@backstage/core-components';\nimport { actionFactories } from './actions';\nimport { columnFactories, defaultColumns } from './columns';\nimport { DocsTableRow } 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 */\nexport const DocsTable = (props: DocsTableProps) => {\n const { entities, title, loading, columns, actions, options } = props;\n const [, copyToClipboard] = useCopyToClipboard();\n const getRouteToReaderPageFor = useRouteRef(rootDocsRouteRef);\n const config = useApi(configApiRef);\n if (!entities) return null;\n\n const documents = entitiesToDocsMapper(\n entities,\n getRouteToReaderPageFor,\n config,\n );\n\n const defaultActions: TableProps<DocsTableRow>['actions'] = [\n actionFactories.createCopyDocsUrlAction(copyToClipboard),\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={columns || defaultColumns}\n actions={actions || defaultActions}\n title={\n title\n ? `${title} (${documents.length})`\n : `All (${documents.length})`\n }\n />\n ) : (\n <EmptyState\n missing=\"data\"\n title=\"No documents to show\"\n description=\"Create your own document. Check out our Getting Started Information\"\n action={\n <LinkButton\n color=\"primary\"\n to=\"https://backstage.io/docs/features/techdocs/getting-started\"\n variant=\"contained\"\n >\n DOCS\n </LinkButton>\n }\n />\n )}\n </>\n );\n};\n\nDocsTable.columns = columnFactories;\nDocsTable.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';\n\n/**\n * Not directly exported, but through DocsTable.actions and EntityListDocsTable.actions\n *\n * @public\n */\nexport const actionFactories = {\n createCopyDocsUrlAction(copyToClipboard: Function) {\n return (row: DocsTableRow) => {\n return {\n icon: () => <ShareIcon fontSize=\"small\" />,\n tooltip: '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 ) {\n return (row: DocsTableRow) => {\n const entity = row.entity;\n const isStarred = isStarredEntity(entity);\n return {\n cellStyle: { paddingLeft: '1em' },\n icon: () => <FavoriteToggleIcon isFavorite={isStarred} />,\n tooltip: isStarred ? 'Remove from favorites' : 'Add to favorites',\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 { Link, SubvalueCell, TableColumn } from '@backstage/core-components';\nimport { EntityRefLinks } from '@backstage/plugin-catalog-react';\nimport { Entity } from '@backstage/catalog-model';\nimport { DocsTableRow } from './types';\n\nfunction customTitle(entity: Entity): string {\n return entity.metadata.title || entity.metadata.name;\n}\n\n/**\n * Not directly exported, but through DocsTable.columns and EntityListDocsTable.columns\n *\n * @public\n */\nexport const columnFactories = {\n createTitleColumn(options?: { hidden?: boolean }): TableColumn<DocsTableRow> {\n const nameCol = columnFactories.createNameColumn();\n return {\n ...nameCol,\n field: 'entity.metadata.title',\n hidden: options?.hidden,\n };\n },\n createNameColumn(): TableColumn<DocsTableRow> {\n return {\n title: '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).toLocaleLowerCase();\n const title2 = customTitle(row2.entity).toLocaleLowerCase();\n return title1.localeCompare(title2);\n },\n render: (row: DocsTableRow) => (\n <SubvalueCell\n value={\n <Link to={row.resolved.docsUrl}>{customTitle(row.entity)}</Link>\n }\n subvalue={row.entity.metadata.description}\n />\n ),\n };\n },\n createOwnerColumn(): TableColumn<DocsTableRow> {\n return {\n title: '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: 'Kind',\n field: 'entity.kind',\n };\n },\n createTypeColumn(): TableColumn<DocsTableRow> {\n return {\n title: '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 getEntityRelations,\n humanizeEntityRef,\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) {\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(r => humanizeEntityRef(r, { defaultKind: 'group' }))\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 { ReactNode, FC } from 'react';\n\nimport { PageWithHeader } from '@backstage/core-components';\nimport { useApi, configApiRef } from '@backstage/core-plugin-api';\n\n/**\n * Props for {@link TechDocsPageWrapper}\n *\n * @public\n */\nexport type TechDocsPageWrapperProps = {\n children?: ReactNode;\n CustomPageWrapper?: FC<{ children?: ReactNode }>;\n};\n\n/**\n * Component wrapping a TechDocs page with Page and Header components\n *\n * @public\n */\nexport const TechDocsPageWrapper = (props: TechDocsPageWrapperProps) => {\n const { children, CustomPageWrapper } = props;\n const configApi = useApi(configApiRef);\n const generatedSubtitle = `Documentation available in ${\n configApi.getOptionalString('organization.name') ?? 'Backstage'\n }`;\n\n return (\n <>\n {CustomPageWrapper ? (\n <CustomPageWrapper>{children}</CustomPageWrapper>\n ) : (\n <PageWithHeader\n title=\"Documentation\"\n subtitle={generatedSubtitle}\n themeId=\"documentation\"\n >\n {children}\n </PageWithHeader>\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 { CompoundEntityRef } from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport {\n DiscoveryApi,\n FetchApi,\n IdentityApi,\n} from '@backstage/core-plugin-api';\nimport { NotFoundError, ResponseError } from '@backstage/errors';\nimport {\n SyncResult,\n TechDocsApi,\n TechDocsEntityMetadata,\n TechDocsMetadata,\n TechDocsStorageApi,\n} from '@backstage/plugin-techdocs-react';\nimport { fetchEventSource } from '@microsoft/fetch-event-source';\n\n/**\n * API to talk to `techdocs-backend`.\n *\n * @public\n */\nexport class TechDocsClient implements TechDocsApi {\n public configApi: Config;\n public discoveryApi: DiscoveryApi;\n private fetchApi: FetchApi;\n\n constructor(options: {\n configApi: Config;\n discoveryApi: DiscoveryApi;\n fetchApi: FetchApi;\n }) {\n this.configApi = options.configApi;\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi;\n }\n\n public async getCookie(): Promise<{ expiresAt: string }> {\n const apiOrigin = await this.getApiOrigin();\n const requestUrl = `${apiOrigin}/cookie`;\n const response = await this.fetchApi.fetch(`${requestUrl}`, {\n credentials: 'include',\n });\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n return await response.json();\n }\n\n async getApiOrigin(): Promise<string> {\n return await this.discoveryApi.getBaseUrl('techdocs');\n }\n\n /**\n * Retrieve TechDocs metadata.\n *\n * When docs are built, we generate a techdocs_metadata.json and store it along with the generated\n * static files. It includes necessary data about the docs site. This method requests techdocs-backend\n * which retrieves the TechDocs metadata.\n *\n * @param entityId - Object containing entity data like name, namespace, etc.\n */\n async getTechDocsMetadata(\n entityId: CompoundEntityRef,\n ): Promise<TechDocsMetadata> {\n const { kind, namespace, name } = entityId;\n\n const apiOrigin = await this.getApiOrigin();\n const requestUrl = `${apiOrigin}/metadata/techdocs/${namespace}/${kind}/${name}`;\n const request = await this.fetchApi.fetch(`${requestUrl}`);\n if (!request.ok) {\n throw await ResponseError.fromResponse(request);\n }\n\n return await request.json();\n }\n\n /**\n * Retrieve metadata about an entity.\n *\n * This method requests techdocs-backend which uses the catalog APIs to respond with filtered\n * information required here.\n *\n * @param entityId - Object containing entity data like name, namespace, etc.\n */\n async getEntityMetadata(\n entityId: CompoundEntityRef,\n ): Promise<TechDocsEntityMetadata> {\n const { kind, namespace, name } = entityId;\n\n const apiOrigin = await this.getApiOrigin();\n const requestUrl = `${apiOrigin}/metadata/entity/${namespace}/${kind}/${name}`;\n\n const request = await this.fetchApi.fetch(`${requestUrl}`);\n if (!request.ok) {\n throw await ResponseError.fromResponse(request);\n }\n\n return await request.json();\n }\n}\n\n/**\n * API which talks to TechDocs storage to fetch files to render.\n *\n * @public\n */\nexport class TechDocsStorageClient implements TechDocsStorageApi {\n public configApi: Config;\n public discoveryApi: DiscoveryApi;\n private fetchApi: FetchApi;\n\n constructor(options: {\n configApi: Config;\n discoveryApi: DiscoveryApi;\n fetchApi: FetchApi;\n /** @deprecated identityApi is not needed any more */\n identityApi?: IdentityApi;\n }) {\n this.configApi = options.configApi;\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi;\n }\n\n async getApiOrigin(): Promise<string> {\n return await this.discoveryApi.getBaseUrl('techdocs');\n }\n\n async getStorageUrl(): Promise<string> {\n return (\n this.configApi.getOptionalString('techdocs.storageUrl') ??\n `${await this.discoveryApi.getBaseUrl('techdocs')}/static/docs`\n );\n }\n\n async getBuilder(): Promise<string> {\n return this.configApi.getOptionalString('techdocs.builder') || 'local';\n }\n\n /**\n * Fetch HTML content as text for an individual docs page in an entity's docs site.\n *\n * @param entityId - Object containing entity data like name, namespace, etc.\n * @param path - The unique path to an individual docs page e.g. overview/what-is-new\n * @returns HTML content of the docs page as string\n * @throws Throws error when the page is not found.\n */\n async getEntityDocs(\n entityId: CompoundEntityRef,\n path: string,\n ): Promise<string> {\n const { kind, namespace, name } = entityId;\n\n const storageUrl = await this.getStorageUrl();\n const url = `${storageUrl}/${namespace}/${kind}/${name}/${path}`;\n\n const request = await this.fetchApi.fetch(\n `${url.endsWith('/') ? url : `${url}/`}index.html`,\n );\n\n let errorMessage = '';\n switch (request.status) {\n case 404:\n errorMessage = 'Page not found. ';\n // path is empty for the home page of an entity's docs site\n if (!path) {\n errorMessage +=\n 'This could be because there is no index.md file in the root of the docs directory of this repository.';\n }\n throw new NotFoundError(errorMessage);\n case 500:\n errorMessage =\n 'Could not generate documentation or an error in the TechDocs backend. ';\n throw new Error(errorMessage);\n default:\n // Do nothing\n break;\n }\n\n return request.text();\n }\n\n /**\n * Check if docs are on the latest version and trigger rebuild if not\n *\n * @param entityId - Object containing entity data like name, namespace, etc.\n * @param logHandler - Callback to receive log messages from the build process\n * @returns Whether documents are currently synchronized to newest version\n * @throws Throws error on error from sync endpoint in TechDocs Backend\n */\n async syncEntityDocs(\n entityId: CompoundEntityRef,\n logHandler: (line: string) => void = () => {},\n ): Promise<SyncResult> {\n const { kind, namespace, name } = entityId;\n\n const apiOrigin = await this.getApiOrigin();\n const url = `${apiOrigin}/sync/${namespace}/${kind}/${name}`;\n\n return new Promise((resolve, reject) => {\n const ctrl = new AbortController();\n fetchEventSource(url, {\n fetch: this.fetchApi.fetch,\n signal: ctrl.signal,\n onmessage(e: any) {\n if (e.event === 'log') {\n if (e.data) {\n logHandler(JSON.parse(e.data));\n }\n } else if (e.event === 'finish') {\n let updated: boolean = false;\n if (e.data) {\n ({ updated } = JSON.parse(e.data));\n }\n resolve(updated ? 'updated' : 'cached');\n } else if (e.event === 'error') {\n reject(new Error(e.data));\n }\n },\n onerror(err) {\n ctrl.abort();\n reject(err);\n throw err; // rethrow to stop the operation\n },\n });\n });\n }\n\n async getBaseUrl(\n oldBaseUrl: string,\n entityId: CompoundEntityRef,\n path: string,\n ): Promise<string> {\n const { kind, namespace, name } = entityId;\n\n const apiOrigin = await this.getApiOrigin();\n const newBaseUrl = `${apiOrigin}/static/docs/${namespace}/${kind}/${name}/${path}`;\n\n return new URL(\n oldBaseUrl,\n newBaseUrl.endsWith('/') ? newBaseUrl : `${newBaseUrl}/`,\n ).toString();\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 techdocsApiRef,\n techdocsStorageApiRef,\n} from '@backstage/plugin-techdocs-react';\nimport { TechDocsClient, TechDocsStorageClient } from './client';\nimport {\n rootDocsRouteRef,\n rootRouteRef,\n rootCatalogDocsRouteRef,\n} from './routes';\nimport {\n configApiRef,\n createApiFactory,\n createPlugin,\n createRoutableExtension,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/core-plugin-api';\nimport {\n createSearchResultListItemExtension,\n SearchResultListItemExtensionProps,\n} from '@backstage/plugin-search-react';\nimport { TechDocsSearchResultListItemProps } from './search/components/TechDocsSearchResultListItem';\n\n/**\n * The Backstage plugin that renders technical documentation for your components\n *\n * @public\n */\nexport const techdocsPlugin = createPlugin({\n id: 'techdocs',\n apis: [\n createApiFactory({\n api: techdocsStorageApiRef,\n deps: {\n configApi: configApiRef,\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ configApi, discoveryApi, fetchApi }) =>\n new TechDocsStorageClient({\n configApi,\n discoveryApi,\n fetchApi,\n }),\n }),\n createApiFactory({\n api: techdocsApiRef,\n deps: {\n configApi: configApiRef,\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ configApi, discoveryApi, fetchApi }) =>\n new TechDocsClient({\n configApi,\n discoveryApi,\n fetchApi,\n }),\n }),\n ],\n routes: {\n root: rootRouteRef,\n docRoot: rootDocsRouteRef,\n entityContent: rootCatalogDocsRouteRef,\n },\n});\n\n/**\n * Routable extension used to render docs\n *\n * @public\n */\nexport const TechdocsPage = techdocsPlugin.provide(\n createRoutableExtension({\n name: 'TechdocsPage',\n component: () => import('./Router').then(m => m.Router),\n mountPoint: rootRouteRef,\n }),\n);\n\n/**\n * Routable extension used to render docs on Entity page\n *\n * @public\n */\nexport const EntityTechdocsContent = techdocsPlugin.provide(\n createRoutableExtension({\n name: 'EntityTechdocsContent',\n component: () => import('./Router').then(m => m.LegacyEmbeddedDocsRouter),\n mountPoint: rootCatalogDocsRouteRef,\n }),\n);\n\n/**\n * Component which takes a custom tabs config object and renders a documentation landing page.\n *\n * @public\n */\nexport const TechDocsCustomHome = techdocsPlugin.provide(\n createRoutableExtension({\n name: 'TechDocsCustomHome',\n component: () =>\n import('./home/components/TechDocsCustomHome').then(\n m => m.TechDocsCustomHome,\n ),\n mountPoint: rootRouteRef,\n }),\n);\n\n/**\n * Responsible for rendering the provided router element\n *\n * @public\n */\nexport const TechDocsIndexPage = techdocsPlugin.provide(\n createRoutableExtension({\n name: 'TechDocsIndexPage',\n component: () =>\n import('./home/components/TechDocsIndexPage').then(\n m => m.TechDocsIndexPage,\n ),\n mountPoint: rootRouteRef,\n }),\n);\n\n/**\n * Component responsible for composing a TechDocs reader page experience\n *\n * @public\n */\nexport const TechDocsReaderPage = techdocsPlugin.provide(\n createRoutableExtension({\n name: 'TechDocsReaderPage',\n component: () =>\n import('./reader/components/TechDocsReaderPage').then(\n m => m.TechDocsReaderPage,\n ),\n mountPoint: rootDocsRouteRef,\n }),\n);\n\n/**\n * React extension used to render results on Search page or modal\n *\n * @public\n */\nexport const TechDocsSearchResultListItem: (\n props: SearchResultListItemExtensionProps<TechDocsSearchResultListItemProps>,\n) => JSX.Element | null = techdocsPlugin.provide(\n createSearchResultListItemExtension({\n name: 'TechDocsSearchResultListItem',\n component: () =>\n import('./search/components/TechDocsSearchResultListItem').then(\n m => m.TechDocsSearchResultListItem,\n ),\n predicate: result => result.type === 'techdocs',\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\nlet ReactDOMPromise: Promise<\n typeof import('react-dom') | typeof import('react-dom/client')\n>;\nif (process.env.HAS_REACT_DOM_CLIENT) {\n ReactDOMPromise = import('react-dom/client');\n} else {\n ReactDOMPromise = import('react-dom');\n}\n\n/** @internal */\nexport function renderReactElement(element: JSX.Element, root: HTMLElement) {\n ReactDOMPromise.then(ReactDOM => {\n if ('createRoot' in ReactDOM) {\n ReactDOM.createRoot(root).render(element);\n } else {\n ReactDOM.render(element, root);\n }\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 */\n\nimport { ChangeEvent, useCallback, useMemo } from 'react';\n\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Autocomplete, {\n AutocompleteProps,\n AutocompleteRenderInputParams,\n} from '@material-ui/lab/Autocomplete';\nimport {\n AutocompleteChangeDetails,\n AutocompleteChangeReason,\n} from '@material-ui/lab/useAutocomplete';\n\nimport { SearchContextProvider, useSearch } from '../../context';\nimport { SearchBar, SearchBarProps } from '../SearchBar';\n\nconst useStyles = makeStyles(theme => ({\n loading: {\n right: theme.spacing(1),\n position: 'absolute',\n },\n}));\n\n/**\n * Props for {@link SearchAutocomplete}.\n *\n * @public\n */\nexport type SearchAutocompleteProps<Option> = Omit<\n AutocompleteProps<Option, undefined, undefined, boolean>,\n 'renderInput' | 'disableClearable' | 'multiple'\n> & {\n 'data-testid'?: string;\n inputPlaceholder?: SearchBarProps['placeholder'];\n inputDebounceTime?: SearchBarProps['debounceTime'];\n};\n\n/**\n * Type for {@link SearchAutocomplete}.\n *\n * @public\n */\nexport type SearchAutocompleteComponent = <Option>(\n props: SearchAutocompleteProps<Option>,\n) => JSX.Element;\n\nconst withContext = (\n Component: SearchAutocompleteComponent,\n): SearchAutocompleteComponent => {\n return props => (\n <SearchContextProvider inheritParentContextIfAvailable>\n <Component {...props} />\n </SearchContextProvider>\n );\n};\n\nconst SearchAutocompleteLoadingAdornment = () => {\n const classes = useStyles();\n return (\n <CircularProgress\n className={classes.loading}\n data-testid=\"search-autocomplete-progressbar\"\n color=\"inherit\"\n size={20}\n />\n );\n};\n\n/**\n * Recommended search autocomplete when you use the Search Provider or Search Context.\n *\n * @public\n */\nexport const SearchAutocomplete = withContext(\n function SearchAutocompleteComponent<Option>(\n props: SearchAutocompleteProps<Option>,\n ) {\n const {\n loading,\n value,\n onChange = () => {},\n options = [],\n getOptionLabel = (option: Option) => String(option),\n inputPlaceholder,\n inputDebounceTime,\n freeSolo = true,\n fullWidth = true,\n clearOnBlur = false,\n 'data-testid': dataTestId = 'search-autocomplete',\n ...rest\n } = props;\n\n const { setTerm } = useSearch();\n\n const getInputValue = useCallback(\n (option?: null | string | Option) => {\n if (!option) return '';\n if (typeof option === 'string') return option;\n return getOptionLabel(option);\n },\n [getOptionLabel],\n );\n\n const inputValue = useMemo(\n () => getInputValue(value),\n [value, getInputValue],\n );\n\n const handleChange = useCallback(\n (\n event: ChangeEvent<{}>,\n option: null | string | Option,\n reason: AutocompleteChangeReason,\n details?: AutocompleteChangeDetails<Option>,\n ) => {\n setTerm(getInputValue(option));\n onChange(event, option, reason, details);\n },\n [getInputValue, setTerm, onChange],\n );\n\n const renderInput = useCallback(\n ({\n InputProps: { ref, className, endAdornment },\n InputLabelProps,\n ...params\n }: AutocompleteRenderInputParams) => (\n <SearchBar\n {...params}\n ref={ref}\n clearButton={false}\n value={inputValue}\n placeholder={inputPlaceholder}\n debounceTime={inputDebounceTime}\n endAdornment={\n loading ? <SearchAutocompleteLoadingAdornment /> : endAdornment\n }\n InputProps={{ className }}\n />\n ),\n [loading, inputValue, inputPlaceholder, inputDebounceTime],\n );\n\n return (\n <Autocomplete\n {...rest}\n data-testid={dataTestId}\n value={value}\n onChange={handleChange}\n options={options}\n getOptionLabel={getOptionLabel}\n renderInput={renderInput}\n freeSolo={freeSolo}\n fullWidth={fullWidth}\n clearOnBlur={clearOnBlur}\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 { ComponentType, createContext, useContext, ReactNode } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useTechDocsReaderPage } from '@backstage/plugin-techdocs-react';\n\nimport { useReaderState, ReaderState } from './useReaderState';\n\nconst TechDocsReaderContext = createContext<ReaderState>({} as ReaderState);\n\nexport const useTechDocsReader = () => useContext(TechDocsReaderContext);\n\n/**\n * @public Render function for {@link TechDocsReaderProvider}\n */\nexport type TechDocsReaderProviderRenderFunction = (\n value: ReaderState,\n) => JSX.Element;\n\n/**\n * @public Props for {@link TechDocsReaderProvider}\n */\nexport type TechDocsReaderProviderProps = {\n children: TechDocsReaderProviderRenderFunction | ReactNode;\n};\n\n/**\n * Provides shared building process state to the reader page components.\n *\n * @public\n */\nexport const TechDocsReaderProvider = (props: TechDocsReaderProviderProps) => {\n const { children } = props;\n\n const { '*': path = '' } = useParams();\n const { entityRef } = useTechDocsReaderPage();\n const { kind, namespace, name } = entityRef;\n const value = useReaderState(kind, namespace, name, path);\n\n return (\n <TechDocsReaderContext.Provider value={value}>\n {children instanceof Function ? children(value) : children}\n </TechDocsReaderContext.Provider>\n );\n};\n\nexport const withTechDocsReaderProvider =\n <T extends {}>(Component: ComponentType<T>) =>\n (props: T) =>\n (\n <TechDocsReaderProvider>\n <Component {...props} />\n </TechDocsReaderProvider>\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 */\n\nimport { PropsWithChildren, useState, useEffect, useCallback } from 'react';\n\nimport { create } from 'jss';\nimport StylesProvider from '@material-ui/styles/StylesProvider';\nimport jssPreset from '@material-ui/styles/jssPreset';\n\n/**\n * Name for the event dispatched when ShadowRoot styles are loaded.\n * @public\n */\nexport const SHADOW_DOM_STYLE_LOAD_EVENT = 'TECH_DOCS_SHADOW_DOM_STYLE_LOAD';\n\n/**\n * Dispatch style load event after all styles are loaded.\n * @param element - the ShadowRoot tree.\n */\nconst useShadowDomStylesEvents = (element: Element | null) => {\n useEffect(() => {\n if (!element) {\n return () => {};\n }\n\n const styles = element.querySelectorAll<HTMLElement>(\n 'head > link[rel=\"stylesheet\"]',\n );\n\n let count = styles?.length ?? 0;\n const event = new CustomEvent(SHADOW_DOM_STYLE_LOAD_EVENT);\n\n if (!count) {\n element.dispatchEvent(event);\n return () => {};\n }\n\n const handleLoad = () => {\n if (--count === 0) {\n element.dispatchEvent(event);\n }\n };\n\n styles?.forEach(style => {\n style.addEventListener('load', handleLoad);\n });\n\n return () => {\n styles?.forEach(style => {\n style.removeEventListener('load', handleLoad);\n });\n };\n }, [element]);\n};\n\n/**\n * Returns the style's loading state.\n *\n * @example\n * Here's an example that updates the sidebar position only after styles are calculated:\n * ```jsx\n * import {\n * TechDocsShadowDom,\n * useShadowDomStylesLoading,\n * } from '@backstage/plugin-techdocs-react';\n *\n * export const TechDocsReaderPageContent = () => {\n * // ...\n * const dom = useTechDocsReaderDom(entity);\n * const isStyleLoading = useShadowDomStylesLoading(dom);\n *\n * const updateSidebarPosition = useCallback(() => {\n * //...\n * }, [dom]);\n *\n * useEffect(() => {\n * if (!isStyleLoading) {\n * updateSidebarPosition();\n * }\n * }, [isStyleLoading, updateSidebarPosition]);\n *\n * const handleDomAppend = useCallback(\n * (newShadowRoot: ShadowRoot) => {\n * setShadowRoot(newShadowRoot);\n * },\n * [setShadowRoot],\n * );\n *\n * return <TechDocsShadowDom element={dom} onAppend={handleDomAppend} />;\n * };\n * ```\n *\n * @param element - which is the ShadowRoot tree.\n * @returns a boolean value, true if styles are being loaded.\n * @public\n */\nexport const useShadowDomStylesLoading = (element: Element | null) => {\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n if (!element) return () => {};\n\n setLoading(true);\n\n const style = (element as HTMLElement).style;\n\n style.setProperty('opacity', '0');\n\n const handleLoad = () => {\n setLoading(false);\n style.setProperty('opacity', '1');\n };\n\n element.addEventListener(SHADOW_DOM_STYLE_LOAD_EVENT, handleLoad);\n\n return () => {\n element.removeEventListener(SHADOW_DOM_STYLE_LOAD_EVENT, handleLoad);\n };\n }, [element]);\n\n return loading;\n};\n\n/**\n * Props for {@link TechDocsShadowDom}.\n *\n * @remarks\n * If you want to use portals to render Material UI components in the Shadow DOM,\n * you must render these portals as children because this component wraps its children in a Material UI StylesProvider\n * to ensure that Material UI styles are applied.\n *\n * @public\n */\nexport type TechDocsShadowDomProps = PropsWithChildren<{\n /**\n * Element tree that is appended to ShadowRoot.\n */\n element: Element;\n /**\n * Callback called when the element tree is appended in ShadowRoot.\n */\n onAppend?: (shadowRoot: ShadowRoot) => void;\n}>;\n\n/**\n * Renders a tree of elements in a Shadow DOM.\n *\n * @remarks\n * Centers the styles loaded event to avoid having multiple locations setting the opacity style in Shadow DOM causing the screen to flash multiple times,\n * so if you want to know when Shadow DOM styles are computed, you can listen for the \"TECH_DOCS_SHADOW_DOM_STYLE_LOAD\" event dispatched by the element tree.\n *\n * @example\n * Here is an example using this component and also listening for styles loaded event:\n *```jsx\n * import {\n * TechDocsShadowDom,\n * SHADOW_DOM_STYLE_LOAD_EVENT,\n * } from '@backstage/plugin-techdocs-react';\n *\n * export const TechDocsReaderPageContent = ({ entity }: TechDocsReaderPageContentProps) => {\n * // ...\n * const dom = useTechDocsReaderDom(entity);\n *\n * useEffect(() => {\n * const updateSidebarPosition = () => {\n * // ...\n * };\n * dom?.addEventListener(SHADOW_DOM_STYLE_LOAD_EVENT, updateSidebarPosition);\n * return () => {\n * dom?.removeEventListener(SHADOW_DOM_STYLE_LOAD_EVENT, updateSidebarPosition);\n * };\n * }, [dom]);\n *\n * const handleDomAppend = useCallback(\n * (newShadowRoot: ShadowRoot) => {\n * setShadowRoot(newShadowRoot);\n * },\n * [setShadowRoot],\n * );\n *\n * return <TechDocsShadowDom element={dom} onAppend={handleDomAppend} />;\n * };\n * ```\n *\n * @param props - see {@link TechDocsShadowDomProps}.\n * @public\n */\nexport const TechDocsShadowDom = (props: TechDocsShadowDomProps) => {\n const { element, onAppend, children } = props;\n\n const [jss, setJss] = useState(\n create({\n ...jssPreset(),\n insertionPoint: undefined,\n }),\n );\n\n useShadowDomStylesEvents(element);\n\n const ref = useCallback(\n (shadowHost: HTMLDivElement) => {\n if (!element || !shadowHost) return;\n\n setJss(\n create({\n ...jssPreset(),\n insertionPoint: element.querySelector('head') || undefined,\n }),\n );\n\n let shadowRoot = shadowHost.shadowRoot;\n\n if (!shadowRoot) {\n shadowRoot = shadowHost.attachShadow({ mode: 'open' });\n }\n\n shadowRoot.replaceChildren(element);\n\n if (typeof onAppend === 'function') {\n onAppend(shadowRoot);\n }\n },\n [element, onAppend],\n );\n\n return (\n <>\n {/* The sheetsManager={new Map()} is needed in order to deduplicate the injection of CSS in the page. */}\n <StylesProvider jss={jss} sheetsManager={new Map()}>\n <div ref={ref} data-testid=\"techdocs-native-shadowroot\" />\n {children}\n </StylesProvider>\n </>\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 */\n\nimport { SearchQuery, SearchResultSet } from '@backstage/plugin-search-common';\nimport { createApiRef } from '@backstage/core-plugin-api';\n\n/**\n * @public\n */\nexport const searchApiRef = createApiRef<SearchApi>({\n id: 'plugin.search.queryservice',\n});\n\n/**\n * @public\n */\nexport interface SearchApi {\n query(query: SearchQuery): Promise<SearchResultSet>;\n}\n\n/**\n * @public\n *\n * Search Api Mock that can be used in tests and storybooks\n */\nexport class MockSearchApi implements SearchApi {\n constructor(public mockedResults?: SearchResultSet) {}\n\n query(): Promise<SearchResultSet> {\n return Promise.resolve(this.mockedResults || { results: [] });\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 */\n\nimport { isEqual } from 'lodash';\nimport {\n SetStateAction,\n Dispatch,\n DispatchWithoutAction,\n PropsWithChildren,\n useCallback,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport useAsync, { AsyncState } from 'react-use/esm/useAsync';\nimport usePrevious from 'react-use/esm/usePrevious';\n\nimport {\n createVersionedContext,\n createVersionedValueMap,\n} from '@backstage/version-bridge';\nimport { JsonObject } from '@backstage/types';\nimport {\n AnalyticsContext,\n useApi,\n configApiRef,\n useAnalytics,\n} from '@backstage/core-plugin-api';\nimport { SearchResultSet } from '@backstage/plugin-search-common';\n\nimport { searchApiRef } from '../api';\n\n/**\n *\n * @public\n */\nexport type SearchContextValue = {\n result: AsyncState<SearchResultSet>;\n setTerm: Dispatch<SetStateAction<string>>;\n setTypes: Dispatch<SetStateAction<string[]>>;\n setFilters: Dispatch<SetStateAction<JsonObject>>;\n setPageLimit: Dispatch<SetStateAction<number | undefined>>;\n setPageCursor: Dispatch<SetStateAction<string | undefined>>;\n fetchNextPage?: DispatchWithoutAction;\n fetchPreviousPage?: DispatchWithoutAction;\n} & SearchContextState;\n\n/**\n *\n * @public\n */\nexport type SearchContextState = {\n term: string;\n types: string[];\n filters: JsonObject;\n pageLimit?: number;\n pageCursor?: string;\n};\n\nconst SearchContext = createVersionedContext<{\n 1: SearchContextValue;\n}>('search-context');\n\n/**\n * @public\n *\n * React hook which provides the search context\n */\nexport const useSearch = () => {\n const context = useContext(SearchContext);\n if (!context) {\n throw new Error('useSearch must be used within a SearchContextProvider');\n }\n\n const value = context.atVersion(1);\n if (!value) {\n throw new Error('No SearchContext v1 found');\n }\n return value;\n};\n\n/**\n * @public\n *\n * React hook which checks for an existing search context\n */\nexport const useSearchContextCheck = () => {\n const context = useContext(SearchContext);\n return context !== undefined;\n};\n\n/**\n * The initial state of `SearchContextProvider`.\n *\n */\nconst defaultInitialSearchState: SearchContextState = {\n term: '',\n types: [],\n filters: {},\n pageLimit: undefined,\n pageCursor: undefined,\n};\n\nconst useSearchContextValue = (\n initialValue: SearchContextState = defaultInitialSearchState,\n) => {\n const searchApi = useApi(searchApiRef);\n const analytics = useAnalytics();\n\n const [term, setTerm] = useState<string>(initialValue.term);\n const [types, setTypes] = useState<string[]>(initialValue.types);\n const [filters, setFilters] = useState<JsonObject>(initialValue.filters);\n const [pageLimit, setPageLimit] = useState<number | undefined>(\n initialValue.pageLimit,\n );\n const [pageCursor, setPageCursor] = useState<string | undefined>(\n initialValue.pageCursor,\n );\n\n const prevTerm = usePrevious(term);\n const prevFilters = usePrevious(filters);\n\n const result = useAsync(async () => {\n const resultSet = await searchApi.query({\n term,\n types,\n filters,\n pageLimit,\n pageCursor,\n });\n if (term) {\n analytics.captureEvent('search', term, {\n value: resultSet.numberOfResults,\n });\n }\n return resultSet;\n }, [term, types, filters, pageLimit, pageCursor]);\n\n const hasNextPage =\n !result.loading && !result.error && result.value?.nextPageCursor;\n const hasPreviousPage =\n !result.loading && !result.error && result.value?.previousPageCursor;\n\n const fetchNextPage = useCallback(() => {\n setPageCursor(result.value?.nextPageCursor);\n }, [result.value?.nextPageCursor]);\n\n const fetchPreviousPage = useCallback(() => {\n setPageCursor(result.value?.previousPageCursor);\n }, [result.value?.previousPageCursor]);\n\n useEffect(() => {\n // Any time a term is reset, we want to start from page 0.\n // Only reset the term if it has been modified by the user at least once, the initial state must not reset the term.\n if (prevTerm !== undefined && term !== prevTerm) {\n setPageCursor(undefined);\n }\n }, [term, prevTerm, setPageCursor]);\n\n useEffect(() => {\n // Any time filters is reset, we want to start from page 0.\n // Only reset the page if it has been modified by the user at least once, the initial state must not reset the page.\n if (prevFilters !== undefined && !isEqual(filters, prevFilters)) {\n setPageCursor(undefined);\n }\n }, [filters, prevFilters, setPageCursor]);\n\n const value: SearchContextValue = {\n result,\n term,\n setTerm,\n types,\n setTypes,\n filters,\n setFilters,\n pageLimit,\n setPageLimit,\n pageCursor,\n setPageCursor,\n fetchNextPage: hasNextPage ? fetchNextPage : undefined,\n fetchPreviousPage: hasPreviousPage ? fetchPreviousPage : undefined,\n };\n\n return value;\n};\n\nexport type LocalSearchContextProps = PropsWithChildren<{\n initialState?: SearchContextState;\n}>;\n\nconst LocalSearchContext = (props: SearchContextProviderProps) => {\n const { initialState, children } = props;\n const value = useSearchContextValue(initialState);\n\n return (\n <AnalyticsContext\n attributes={{ searchTypes: value.types.sort().join(',') }}\n >\n <SearchContext.Provider value={createVersionedValueMap({ 1: value })}>\n {children}\n </SearchContext.Provider>\n </AnalyticsContext>\n );\n};\n\n/**\n * Props for {@link SearchContextProvider}\n *\n * @public\n */\nexport type SearchContextProviderProps =\n | PropsWithChildren<{\n /**\n * State initialized by a local context.\n */\n initialState?: SearchContextState;\n /**\n * Do not create an inheritance from the parent, as a new initial state must be defined in a local context.\n */\n inheritParentContextIfAvailable?: never;\n }>\n | PropsWithChildren<{\n /**\n * Does not accept initial state since it is already initialized by parent context.\n */\n initialState?: never;\n /**\n * If true, don't create a child context if there is a parent one already defined.\n * @remarks Defaults to false.\n */\n inheritParentContextIfAvailable?: boolean;\n }>;\n\n/**\n * @public\n * Search context provider which gives you access to shared state between search components\n */\nexport const SearchContextProvider = (props: SearchContextProviderProps) => {\n const { initialState, inheritParentContextIfAvailable, children } = props;\n const hasParentContext = useSearchContextCheck();\n\n const configApi = useApi(configApiRef);\n\n const propsInitialSearchState = initialState ?? {};\n\n const configInitialSearchState = configApi.has('search.query.pageLimit')\n ? { pageLimit: configApi.getNumber('search.query.pageLimit') }\n : {};\n\n const searchContextInitialState = {\n ...defaultInitialSearchState,\n ...propsInitialSearchState,\n ...configInitialSearchState,\n };\n\n return hasParentContext && inheritParentContextIfAvailable ? (\n <>{children}</>\n ) : (\n <LocalSearchContext initialState={searchContextInitialState}>\n {children}\n </LocalSearchContext>\n );\n};\n","/*\n * Copyright 2025 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 { createTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/**\n * @alpha\n */\nexport const searchReactTranslationRef = createTranslationRef({\n id: 'search-react',\n messages: {\n searchBar: {\n title: 'Search',\n placeholder: 'Search in {{org}}',\n clearButtonTitle: 'Clear',\n },\n searchFilter: {\n allOptionTitle: 'All',\n },\n searchPagination: {\n limitLabel: 'Results per page:',\n limitText: 'of {{num}}',\n },\n noResultsDescription: 'Sorry, no results were found',\n searchResultGroup: {\n linkTitle: 'See All',\n addFilterButtonTitle: 'Add filter',\n },\n searchResultPager: {\n previous: 'Previous',\n next: 'Next',\n },\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 */\n\nimport {\n AnalyticsContext,\n configApiRef,\n useApi,\n useApp,\n} from '@backstage/core-plugin-api';\nimport IconButton from '@material-ui/core/IconButton';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport TextField from '@material-ui/core/TextField';\nimport Button from '@material-ui/core/Button';\nimport { TextFieldProps } from '@material-ui/core/TextField';\nimport DefaultSearchIcon from '@material-ui/icons/Search';\nimport {\n ReactNode,\n ChangeEvent,\n forwardRef,\n KeyboardEvent,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport useDebounce from 'react-use/esm/useDebounce';\nimport { SearchContextProvider, useSearch } from '../../context';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { searchReactTranslationRef } from '../../translation';\n\n/**\n * Props for {@link SearchBarBase}.\n *\n * @public\n */\nexport type SearchBarBaseProps = Omit<TextFieldProps, 'onChange'> & {\n debounceTime?: number;\n clearButton?: boolean;\n onClear?: () => void;\n onSubmit?: () => void;\n onChange: (value: string) => void;\n endAdornment?: ReactNode;\n};\n\n/**\n * All search boxes exported by the search plugin are based on the <SearchBarBase />,\n * and this one is based on the <InputBase /> component from Material UI.\n * Recommended if you don't use Search Provider or Search Context.\n *\n * @public\n */\nexport const SearchBarBase = forwardRef((props: SearchBarBaseProps, ref) => {\n const {\n onChange,\n onKeyDown = () => {},\n onClear = () => {},\n onSubmit = () => {},\n debounceTime = 200,\n clearButton = true,\n fullWidth = true,\n value: defaultValue,\n label,\n placeholder,\n inputProps = {},\n InputProps = {},\n endAdornment,\n ...rest\n } = props;\n\n const configApi = useApi(configApiRef);\n const [value, setValue] = useState<string>('');\n const forwardedValueRef = useRef<string>('');\n const { t } = useTranslationRef(searchReactTranslationRef);\n\n useEffect(() => {\n setValue(prevValue => {\n // We only update the value if our current value is the same as it was\n // for the most recent onChange call. Otherwise it means that the users\n // has continued typing and we should not replace their input.\n if (prevValue === forwardedValueRef.current) {\n return String(defaultValue);\n }\n return prevValue;\n });\n }, [defaultValue, forwardedValueRef]);\n\n useDebounce(\n () => {\n forwardedValueRef.current = value;\n onChange(value);\n },\n debounceTime,\n [value],\n );\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n setValue(e.target.value);\n },\n [setValue],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n if (onKeyDown) onKeyDown(e);\n if (onSubmit && e.key === 'Enter') {\n onSubmit();\n }\n },\n [onKeyDown, onSubmit],\n );\n\n const handleClear = useCallback(() => {\n forwardedValueRef.current = '';\n onChange('');\n setValue('');\n if (onClear) {\n onClear();\n }\n }, [onChange, onClear]);\n\n const ariaLabel: string | undefined = label\n ? undefined\n : t('searchBar.title');\n\n const inputPlaceholder =\n placeholder ??\n t('searchBar.placeholder', {\n org: configApi.getOptionalString('app.title') || 'Backstage',\n });\n const SearchIcon = useApp().getSystemIcon('search') || DefaultSearchIcon;\n\n const startAdornment = (\n <InputAdornment position=\"start\">\n <IconButton aria-label=\"Query\" size=\"small\" disabled>\n <SearchIcon />\n </IconButton>\n </InputAdornment>\n );\n\n const clearButtonEndAdornment = (\n <InputAdornment position=\"end\">\n <Button\n aria-label={t('searchBar.clearButtonTitle')}\n size=\"small\"\n onClick={handleClear}\n onKeyDown={event => {\n if (event.key === 'Enter') {\n // write your functionality here\n event.stopPropagation();\n }\n }}\n >\n {t('searchBar.clearButtonTitle')}\n </Button>\n </InputAdornment>\n );\n\n return (\n <SearchContextProvider inheritParentContextIfAvailable>\n <TextField\n id=\"search-bar-text-field\"\n data-testid=\"search-bar-next\"\n variant=\"outlined\"\n margin=\"normal\"\n inputRef={ref}\n value={value}\n label={label}\n placeholder={inputPlaceholder}\n InputProps={{\n startAdornment,\n endAdornment: clearButton ? clearButtonEndAdornment : endAdornment,\n ...InputProps,\n }}\n inputProps={{\n 'aria-label': ariaLabel,\n ...inputProps,\n }}\n fullWidth={fullWidth}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n {...rest}\n />\n </SearchContextProvider>\n );\n});\n\n/**\n * Props for {@link SearchBar}.\n *\n * @public\n */\nexport type SearchBarProps = Partial<SearchBarBaseProps>;\n\n/**\n * Recommended search bar when you use the Search Provider or Search Context.\n *\n * @public\n */\nexport const SearchBar = forwardRef((props: SearchBarProps, ref) => {\n const { value: initialValue = '', onChange, ...rest } = props;\n\n const { term, setTerm } = useSearch();\n\n useEffect(() => {\n if (initialValue) {\n setTerm(String(initialValue));\n }\n }, [initialValue, setTerm]);\n\n const handleChange = useCallback(\n (newValue: string) => {\n if (onChange) {\n onChange(newValue);\n } else {\n setTerm(newValue);\n }\n },\n [onChange, setTerm],\n );\n\n return (\n <SearchContextProvider inheritParentContextIfAvailable>\n <AnalyticsContext\n attributes={{ pluginId: 'search', extension: 'SearchBar' }}\n >\n <SearchBarBase\n {...rest}\n ref={ref}\n value={term}\n onChange={handleChange}\n />\n </AnalyticsContext>\n </SearchContextProvider>\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 { CompoundEntityRef } from '@backstage/catalog-model';\nimport { ResultHighlight } from '@backstage/plugin-search-common';\nimport {\n SearchAutocomplete,\n SearchContextProvider,\n useSearch,\n} from '@backstage/plugin-search-react';\nimport { useEffect, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { TechDocsSearchResultListItem } from './TechDocsSearchResultListItem';\n\n/**\n * Props for {@link TechDocsSearch}\n *\n * @public\n */\nexport type TechDocsSearchProps = {\n entityId: CompoundEntityRef;\n entityTitle?: string;\n debounceTime?: number;\n searchResultUrlMapper?: (url: string) => string;\n};\n\ntype TechDocsDoc = {\n namespace: string;\n kind: string;\n name: string;\n path: string;\n location: string;\n title: string;\n};\n\ntype TechDocsSearchResult = {\n type: string;\n document: TechDocsDoc;\n highlight?: ResultHighlight;\n};\n\nconst isTechDocsSearchResult = (\n option: any,\n): option is TechDocsSearchResult => {\n return option?.document;\n};\n\nconst TechDocsSearchBar = (props: TechDocsSearchProps) => {\n const {\n entityId,\n entityTitle,\n debounceTime = 150,\n searchResultUrlMapper,\n } = props;\n const [open, setOpen] = useState(false);\n const navigate = useNavigate();\n const {\n setFilters,\n term,\n result: { loading, value: searchVal },\n } = useSearch();\n const [options, setOptions] = useState<any[]>([]);\n useEffect(() => {\n let mounted = true;\n\n if (mounted && searchVal) {\n // TODO: Change this into getting only subset of search results from the BE in the first place\n // once pagination is implemented for search engines\n // See: https://github.com/backstage/backstage/issues/6062\n const searchResults = searchVal.results.slice(0, 10);\n setOptions(searchResults);\n }\n return () => {\n mounted = false;\n };\n }, [loading, searchVal]);\n\n // Update the filter context when the entityId changes, e.g. when the search\n // bar continues to be rendered, navigating between different TechDocs sites.\n const { kind, name, namespace } = entityId;\n useEffect(() => {\n setFilters(prevFilters => {\n return {\n ...prevFilters,\n kind,\n namespace,\n name,\n };\n });\n }, [kind, namespace, name, setFilters]);\n\n const handleSelection = (\n _: any,\n selection: TechDocsSearchResult | string | null,\n ) => {\n if (isTechDocsSearchResult(selection)) {\n const { location } = selection.document;\n navigate(\n searchResultUrlMapper ? searchResultUrlMapper(location) : location,\n );\n }\n };\n\n return (\n <SearchAutocomplete\n data-testid=\"techdocs-search-bar\"\n size=\"small\"\n open={open && Boolean(term)}\n getOptionLabel={() => ''}\n filterOptions={x => {\n return x; // This is needed to get renderOption to be called after options change. Bug in material-ui?\n }}\n onClose={() => {\n setOpen(false);\n }}\n onOpen={() => {\n setOpen(true);\n }}\n onChange={handleSelection}\n blurOnSelect\n noOptionsText=\"No results found\"\n value={null}\n options={options}\n renderOption={({ document, highlight }) => (\n <TechDocsSearchResultListItem\n result={document}\n lineClamp={3}\n asListItem={false}\n asLink={false}\n title={document.title}\n highlight={highlight}\n />\n )}\n loading={loading}\n inputDebounceTime={debounceTime}\n inputPlaceholder={`Search ${entityTitle || entityId.name} docs`}\n freeSolo={false}\n />\n );\n};\n\n/**\n * Component used to render search bar on TechDocs page, scoped to\n *\n * @public\n */\nexport const TechDocsSearch = (props: TechDocsSearchProps) => {\n const initialState = {\n term: '',\n types: ['techdocs'],\n pageCursor: '',\n filters: props.entityId,\n };\n return (\n <SearchContextProvider initialState={initialState}>\n <TechDocsSearchBar {...props} />\n </SearchContextProvider>\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 { lazy, Suspense } from 'react';\nimport { useApp } from '@backstage/core-plugin-api';\n\nconst RealLogViewer = lazy(() =>\n import('./RealLogViewer').then(m => ({ default: m.RealLogViewer })),\n);\n\n/**\n * The properties for the LogViewer component.\n *\n * @public\n */\nexport interface LogViewerProps {\n /**\n * The text of the logs to display.\n *\n * The LogViewer component is optimized for appending content at the end of the text.\n */\n text: string;\n /**\n * Determines if the overflow text should be wrapped or shown via a single line in a horizontal scrollbar.\n */\n textWrap?: boolean;\n /**\n * Styling overrides for classes within the LogViewer component.\n */\n classes?: {\n root?: string;\n };\n}\n\n/**\n * A component that displays logs in a scrollable text area.\n *\n * @remarks\n * The LogViewer has support for search and filtering, as well as displaying\n * text content with ANSI color escape codes.\n *\n * Since the LogViewer uses windowing to avoid rendering all contents at once, the\n * log is sized automatically to fill the available vertical space. This means\n * it may often be needed to wrap the LogViewer in a container that provides it\n * with a fixed amount of space.\n *\n * @public\n */\nexport function LogViewer(props: LogViewerProps) {\n const { Progress } = useApp().getComponents();\n return (\n <Suspense fallback={<Progress />}>\n <RealLogViewer {...props} />\n </Suspense>\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 { LogViewer } from '@backstage/core-components';\nimport Button from '@material-ui/core/Button';\nimport Drawer from '@material-ui/core/Drawer';\nimport Grid from '@material-ui/core/Grid';\nimport IconButton from '@material-ui/core/IconButton';\nimport Typography from '@material-ui/core/Typography';\nimport { createStyles, makeStyles, Theme } from '@material-ui/core/styles';\nimport Close from '@material-ui/icons/Close';\nimport { useState } from 'react';\n\nconst useDrawerStyles = makeStyles((theme: Theme) =>\n createStyles({\n paper: {\n width: '100%',\n [theme.breakpoints.up('sm')]: {\n width: '75%',\n },\n [theme.breakpoints.up('md')]: {\n width: '50%',\n },\n padding: theme.spacing(2.5),\n },\n root: {\n height: '100%',\n overflow: 'hidden',\n },\n logs: {\n background: theme.palette.background.default,\n },\n }),\n);\n\nexport const TechDocsBuildLogsDrawerContent = ({\n buildLog,\n onClose,\n}: {\n buildLog: string[];\n onClose: () => void;\n}) => {\n const classes = useDrawerStyles();\n const logText =\n buildLog.length === 0 ? 'Waiting for logs...' : buildLog.join('\\n');\n return (\n <Grid\n container\n direction=\"column\"\n className={classes.root}\n spacing={0}\n wrap=\"nowrap\"\n >\n <Grid\n item\n container\n justifyContent=\"space-between\"\n alignItems=\"center\"\n spacing={0}\n wrap=\"nowrap\"\n >\n <Typography variant=\"h5\">Build Details</Typography>\n <IconButton\n key=\"dismiss\"\n title=\"Close the drawer\"\n onClick={onClose}\n color=\"inherit\"\n >\n <Close />\n </IconButton>\n </Grid>\n <Grid item xs>\n <LogViewer text={logText} classes={{ root: classes.logs }} />\n </Grid>\n </Grid>\n );\n};\n\nexport const TechDocsBuildLogs = ({ buildLog }: { buildLog: string[] }) => {\n const classes = useDrawerStyles();\n const [open, setOpen] = useState(false);\n\n return (\n <>\n <Button color=\"inherit\" onClick={() => setOpen(true)}>\n Show Build Logs\n </Button>\n <Drawer\n classes={{ paper: classes.paper }}\n anchor=\"right\"\n open={open}\n onClose={() => setOpen(false)}\n >\n <TechDocsBuildLogsDrawerContent\n buildLog={buildLog}\n onClose={() => setOpen(false)}\n />\n </Drawer>\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 { useEffect } from 'react';\nimport { useApi, configApiRef, useAnalytics } from '@backstage/core-plugin-api';\nimport { ErrorPage } from '@backstage/core-components';\nimport { useTechDocsReaderPage } from '@backstage/plugin-techdocs-react';\nimport { useLocation } from 'react-router-dom';\n\ntype Props = {\n errorMessage?: string;\n};\n\nexport const TechDocsNotFound = ({ errorMessage }: Props) => {\n const techdocsBuilder =\n useApi(configApiRef).getOptionalString('techdocs.builder');\n const analyticsApi = useAnalytics();\n const { entityRef } = useTechDocsReaderPage();\n const location = useLocation();\n\n useEffect(() => {\n const { pathname, search, hash } = location;\n analyticsApi.captureEvent('not-found', `${pathname}${search}${hash}`, {\n attributes: entityRef,\n });\n }, [analyticsApi, entityRef, location]);\n\n let additionalInfo = '';\n if (![undefined, 'local'].includes(techdocsBuilder)) {\n additionalInfo =\n \"Note that techdocs.builder is not set to 'local' in your config, which means this Backstage app will not \" +\n \"generate docs if they are not found. Make sure the project's docs are generated and published by some external \" +\n \"process (e.g. CI/CD pipeline). Or change techdocs.builder to 'local' to generate docs from this Backstage \" +\n 'instance.';\n }\n\n return (\n <ErrorPage\n status=\"404\"\n statusMessage={errorMessage || 'Documentation not found'}\n additionalInfo={additionalInfo}\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 { useApi } from '@backstage/core-plugin-api';\nimport { useMemo, useReducer, useRef } from 'react';\nimport useAsync from 'react-use/esm/useAsync';\nimport useAsyncRetry from 'react-use/esm/useAsyncRetry';\nimport { techdocsStorageApiRef } from '@backstage/plugin-techdocs-react';\n\n/**\n * @public\n * A state representation that is used to configure the UI of <Reader />\n */\nexport type ContentStateTypes =\n /** There is nothing to display but a loading indicator */\n | 'CHECKING'\n\n /** There is no content yet -> present a full screen loading page */\n | 'INITIAL_BUILD'\n\n /** There is content, but the backend is about to update it */\n | 'CONTENT_STALE_REFRESHING'\n\n /** There is content, but after a reload, the content will be different */\n | 'CONTENT_STALE_READY'\n\n /** There is content, the backend tried to update it, but failed */\n | 'CONTENT_STALE_ERROR'\n\n /** There is nothing to see but a \"not found\" page. Is also shown on page load errors */\n | 'CONTENT_NOT_FOUND'\n\n /** There is only the latest and greatest content */\n | 'CONTENT_FRESH';\n\n/**\n * Calculate the state that should be reported to the display component.\n */\nexport function calculateDisplayState({\n contentLoading,\n content,\n activeSyncState,\n}: Pick<\n ReducerState,\n 'contentLoading' | 'content' | 'activeSyncState'\n>): ContentStateTypes {\n // we have nothing to display yet\n if (contentLoading) {\n return 'CHECKING';\n }\n\n // the build is ready, but it triggered a content reload and the content variable is not trusted\n if (activeSyncState === 'BUILD_READY_RELOAD') {\n return 'CHECKING';\n }\n\n // there is no content, but the sync process is still evaluating\n if (!content && activeSyncState === 'CHECKING') {\n return 'CHECKING';\n }\n\n // there is no content yet so we assume that we are building it for the first time\n if (!content && activeSyncState === 'BUILDING') {\n return 'INITIAL_BUILD';\n }\n\n // if there is still no content after building, it might just not exist\n if (!content) {\n return 'CONTENT_NOT_FOUND';\n }\n\n // we are still building, but we already show stale content\n if (activeSyncState === 'BUILDING') {\n return 'CONTENT_STALE_REFRESHING';\n }\n\n // the build is ready, but the content is still stale\n if (activeSyncState === 'BUILD_READY') {\n return 'CONTENT_STALE_READY';\n }\n\n // the build failed, but the content is still stale\n if (activeSyncState === 'ERROR') {\n return 'CONTENT_STALE_ERROR';\n }\n\n // seems like the content is up-to-date (or we don't know yet and the sync process is still evaluating in the background)\n return 'CONTENT_FRESH';\n}\n\n/**\n * The state of the synchronization task. It checks whether the docs are\n * up-to-date. If they aren't, it triggers a build.\n */\ntype SyncStates =\n /** Checking if it should be synced */\n | 'CHECKING'\n\n /** Building the documentation */\n | 'BUILDING'\n\n /** Finished building the documentation */\n | 'BUILD_READY'\n\n /**\n * Finished building the documentation and triggered a content reload.\n * This state is left toward UP_TO_DATE when the content loading has finished.\n */\n | 'BUILD_READY_RELOAD'\n\n /** No need for a sync. The content was already up-to-date. */\n | 'UP_TO_DATE'\n\n /** An error occurred */\n | 'ERROR';\n\ntype ReducerActions =\n | {\n type: 'sync';\n state: SyncStates;\n syncError?: Error;\n }\n | { type: 'contentLoading' }\n | {\n type: 'content';\n path?: string;\n content?: string;\n contentError?: Error;\n }\n | { type: 'buildLog'; log: string };\n\ntype ReducerState = {\n /**\n * The path of the current page\n */\n path: string;\n\n /**\n * The current sync state\n */\n activeSyncState: SyncStates;\n\n /**\n * If true, the content is downloading from the storage.\n */\n contentLoading: boolean;\n /**\n * The content that has been downloaded and should be displayed.\n */\n content?: string;\n\n contentError?: Error;\n syncError?: Error;\n\n /**\n * A list of log messages that were emitted by the build process.\n */\n buildLog: string[];\n};\n\nexport function reducer(\n oldState: ReducerState,\n action: ReducerActions,\n): ReducerState {\n const newState = { ...oldState };\n\n switch (action.type) {\n case 'sync':\n // reset the build log when a new check starts\n if (action.state === 'CHECKING') {\n newState.buildLog = [];\n }\n\n newState.activeSyncState = action.state;\n newState.syncError = action.syncError;\n break;\n\n case 'contentLoading':\n newState.contentLoading = true;\n\n // only reset errors but keep the old content until it is replaced by the 'content' action\n newState.contentError = undefined;\n break;\n\n case 'content':\n // only override the path if it is part of the action\n if (typeof action.path === 'string') {\n newState.path = action.path;\n }\n\n newState.contentLoading = false;\n newState.content = action.content;\n newState.contentError = action.contentError;\n break;\n\n case 'buildLog':\n newState.buildLog = newState.buildLog.concat(action.log);\n break;\n\n default:\n throw new Error();\n }\n\n // a content update loads fresh content so the build is updated to being up-to-date\n if (\n ['BUILD_READY', 'BUILD_READY_RELOAD'].includes(newState.activeSyncState) &&\n ['contentLoading', 'content'].includes(action.type)\n ) {\n newState.activeSyncState = 'UP_TO_DATE';\n newState.buildLog = [];\n }\n\n return newState;\n}\n/**\n * @public shared reader state\n */\nexport type ReaderState = {\n state: ContentStateTypes;\n path: string;\n contentReload: () => void;\n content?: string;\n contentErrorMessage?: string;\n syncErrorMessage?: string;\n buildLog: string[];\n};\n\nexport function useReaderState(\n kind: string,\n namespace: string,\n name: string,\n path: string,\n): ReaderState {\n const [state, dispatch] = useReducer(reducer, {\n activeSyncState: 'CHECKING',\n path,\n contentLoading: true,\n buildLog: [],\n });\n\n const techdocsStorageApi = useApi(techdocsStorageApiRef);\n\n // try to load the content. the function will fire events and we don't care for the return values\n const { retry: contentReload } = useAsyncRetry(async () => {\n dispatch({ type: 'contentLoading' });\n\n try {\n const entityDocs = await techdocsStorageApi.getEntityDocs(\n { kind, namespace, name },\n path,\n );\n\n // update content and path at the same time\n dispatch({ type: 'content', content: entityDocs, path });\n\n return entityDocs;\n } catch (e) {\n dispatch({ type: 'content', contentError: e, path });\n }\n\n return undefined;\n }, [techdocsStorageApi, kind, namespace, name, path]);\n\n // create a ref that holds the latest content. This provides a useAsync hook\n // with the latest content without restarting the useAsync hook.\n const contentRef = useRef<{ content?: string; reload: () => void }>({\n content: undefined,\n reload: () => {},\n });\n contentRef.current = { content: state.content, reload: contentReload };\n\n // try to derive the state. the function will fire events and we don't care for the return values\n useAsync(async () => {\n dispatch({ type: 'sync', state: 'CHECKING' });\n\n // should only switch to BUILDING if the request takes more than 1 seconds\n const buildingTimeout = setTimeout(() => {\n dispatch({ type: 'sync', state: 'BUILDING' });\n }, 1000);\n\n try {\n const result = await techdocsStorageApi.syncEntityDocs(\n {\n kind,\n namespace,\n name,\n },\n log => {\n dispatch({ type: 'buildLog', log });\n },\n );\n\n switch (result) {\n case 'updated':\n // if there was no content prior to building, retry the loading\n if (!contentRef.current.content) {\n contentRef.current.reload();\n dispatch({ type: 'sync', state: 'BUILD_READY_RELOAD' });\n } else {\n dispatch({ type: 'sync', state: 'BUILD_READY' });\n }\n break;\n case 'cached':\n dispatch({ type: 'sync', state: 'UP_TO_DATE' });\n break;\n\n default:\n dispatch({\n type: 'sync',\n state: 'ERROR',\n syncError: new Error('Unexpected return state'),\n });\n break;\n }\n } catch (e) {\n dispatch({ type: 'sync', state: 'ERROR', syncError: e });\n } finally {\n // Cancel the timer that sets the state \"BUILDING\"\n clearTimeout(buildingTimeout);\n }\n }, [kind, name, namespace, techdocsStorageApi, dispatch, contentRef]);\n\n const displayState = useMemo(\n () =>\n calculateDisplayState({\n activeSyncState: state.activeSyncState,\n contentLoading: state.contentLoading,\n content: state.content,\n }),\n [state.activeSyncState, state.content, state.contentLoading],\n );\n\n return useMemo(\n () => ({\n state: displayState,\n contentReload,\n path: state.path,\n content: state.content,\n contentErrorMessage: state.contentError?.toString(),\n syncErrorMessage: state.syncError?.toString(),\n buildLog: state.buildLog,\n }),\n [\n displayState,\n contentReload,\n state.path,\n state.content,\n state.contentError,\n state.syncError,\n state.buildLog,\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 CircularProgress from '@material-ui/core/CircularProgress';\nimport Button from '@material-ui/core/Button';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Alert from '@material-ui/lab/Alert';\n\nimport { TechDocsBuildLogs } from './TechDocsBuildLogs';\nimport { TechDocsNotFound } from './TechDocsNotFound';\nimport { useTechDocsReader } from './TechDocsReaderProvider';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n marginBottom: theme.spacing(2),\n },\n message: {\n // `word-break: break-word` is deprecated, but gives legacy support to browsers not supporting `overflow-wrap` yet\n // https://developer.mozilla.org/en-US/docs/Web/CSS/word-break\n wordBreak: 'break-word',\n overflowWrap: 'anywhere',\n },\n}));\n\nexport const TechDocsStateIndicator = () => {\n let StateAlert: JSX.Element | null = null;\n const classes = useStyles();\n\n const {\n state,\n contentReload,\n contentErrorMessage,\n syncErrorMessage,\n buildLog,\n } = useTechDocsReader();\n\n if (state === 'INITIAL_BUILD') {\n StateAlert = (\n <Alert\n classes={{ root: classes.root }}\n variant=\"outlined\"\n severity=\"info\"\n icon={<CircularProgress size=\"24px\" />}\n action={<TechDocsBuildLogs buildLog={buildLog} />}\n >\n Documentation is accessed for the first time and is being prepared. The\n subsequent loads are much faster.\n </Alert>\n );\n }\n\n if (state === 'CONTENT_STALE_REFRESHING') {\n StateAlert = (\n <Alert\n variant=\"outlined\"\n severity=\"info\"\n icon={<CircularProgress size=\"24px\" />}\n action={<TechDocsBuildLogs buildLog={buildLog} />}\n classes={{ root: classes.root }}\n >\n A newer version of this documentation is being prepared and will be\n available shortly.\n </Alert>\n );\n }\n\n if (state === 'CONTENT_STALE_READY') {\n StateAlert = (\n <Alert\n variant=\"outlined\"\n severity=\"success\"\n action={\n <Button color=\"inherit\" onClick={() => contentReload()}>\n Refresh\n </Button>\n }\n classes={{ root: classes.root }}\n >\n A newer version of this documentation is now available, please refresh\n to view.\n </Alert>\n );\n }\n\n if (state === 'CONTENT_STALE_ERROR') {\n StateAlert = (\n <Alert\n variant=\"outlined\"\n severity=\"error\"\n action={<TechDocsBuildLogs buildLog={buildLog} />}\n classes={{ root: classes.root, message: classes.message }}\n >\n Building a newer version of this documentation failed.{' '}\n {syncErrorMessage}\n </Alert>\n );\n }\n\n if (state === 'CONTENT_NOT_FOUND') {\n StateAlert = (\n <>\n {syncErrorMessage && (\n <Alert\n variant=\"outlined\"\n severity=\"error\"\n action={<TechDocsBuildLogs buildLog={buildLog} />}\n classes={{ root: classes.root, message: classes.message }}\n >\n Building a newer version of this documentation failed.{' '}\n {syncErrorMessage}\n </Alert>\n )}\n <TechDocsNotFound errorMessage={contentErrorMessage} />\n </>\n );\n }\n\n return StateAlert;\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 */\n\nconst MKDOCS_CSS = /main\\.[A-Fa-f0-9]{8}\\.min\\.css$/;\nconst GOOGLE_FONTS = /^https:\\/\\/fonts\\.googleapis\\.com/;\nconst GSTATIC_FONTS = /^https:\\/\\/fonts\\.gstatic\\.com/;\n\n/**\n * Checks whether a node is link or not.\n * @param node - can be any element.\n * @returns true when node is link.\n */\nconst isLink = (node: Element) => node.nodeName === 'LINK';\n\n/**\n * Checks whether a link is safe or not.\n * @param node - is an link element.\n * @returns true when link is mkdocs css, google fonts or gstatic fonts.\n */\nconst isSafe = (node: Element) => {\n const href = node?.getAttribute('href') || '';\n const isMkdocsCss = href.match(MKDOCS_CSS);\n const isGoogleFonts = href.match(GOOGLE_FONTS);\n const isGstaticFonts = href.match(GSTATIC_FONTS);\n return isMkdocsCss || isGoogleFonts || isGstaticFonts;\n};\n\n/**\n * Function that removes unsafe link nodes.\n * @param node - can be any element.\n * @param hosts - list of allowed hosts.\n */\nexport const removeUnsafeLinks = (node: Element) => {\n if (isLink(node) && !isSafe(node)) {\n node.remove();\n }\n return node;\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 */\n\nimport { RuleOptions } from './types';\n\ntype RuleTypography = RuleOptions['theme']['typography'];\n\ntype BackstageTypography = RuleTypography & {\n htmlFontSize?: number;\n};\n\ntype TypographyHeadings = Pick<\n RuleTypography,\n 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n>;\n\ntype TypographyHeadingsKeys = keyof TypographyHeadings;\n\nconst headings: TypographyHeadingsKeys[] = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];\nconst relativeLengthUnit: RegExp = /(em)|(rem)/gi;\nconst cssVariable: RegExp = /var\\(|\\)/gi;\n\nexport default ({ theme }: RuleOptions) => `\n/*================== Typeset ==================*/\n\n.md-typeset {\n font-size: var(--md-typeset-font-size);\n}\n\n${headings.reduce<string>((style, heading) => {\n const htmlFontSize =\n (theme.typography as BackstageTypography).htmlFontSize ?? 16;\n const styles = theme.typography[heading];\n const { lineHeight, fontFamily, fontWeight, fontSize } = styles;\n const calculate = (value: typeof fontSize): string | undefined => {\n if (typeof value === 'number') {\n // Convert px to rem and apply 60% factor\n return calculate(`${(value / htmlFontSize) * 0.6}rem`);\n } else if (typeof value === 'string') {\n if (value.match(cssVariable)) {\n // Resolve css variable and calculate recursively\n const resolvedValue = window\n .getComputedStyle(document.body)\n .getPropertyValue(value.replaceAll(cssVariable, ''));\n if (resolvedValue !== '') {\n return calculate(resolvedValue);\n }\n } else if (value.match(relativeLengthUnit)) {\n // Use relative size as factor\n const factor = value.replace(relativeLengthUnit, '');\n return `calc(${factor} * var(--md-typeset-font-size))`;\n }\n }\n // Value is not a number, relative length unit, or CSS variable, return as is\n return value;\n };\n return style.concat(`\n .md-typeset ${heading} {\n color: var(--md-default-fg-color);\n line-height: ${lineHeight};\n font-family: ${fontFamily};\n font-weight: ${fontWeight};\n font-size: ${calculate(fontSize)};\n }\n `);\n}, '')}\n\n.md-typeset .md-content__button {\n color: var(--md-default-fg-color);\n}\n\n.md-typeset hr {\n border-bottom: 0.05rem dotted ${theme.palette.divider};\n}\n\n.md-typeset details {\n font-size: var(--md-typeset-font-size) !important;\n}\n.md-typeset details summary {\n padding-left: 2.5rem !important;\n}\n.md-typeset details summary:before,\n.md-typeset details summary:after {\n top: 50% !important;\n width: 20px !important;\n height: 20px !important;\n transform: rotate(0deg) translateY(-50%) !important;\n}\n.md-typeset details[open] > summary:after {\n transform: rotate(90deg) translateX(-50%) !important;\n}\n\n.md-typeset blockquote {\n color: var(--md-default-fg-color--light);\n border-left: 0.2rem solid var(--md-default-fg-color--light);\n}\n\n.md-typeset table:not([class]) {\n font-size: var(--md-typeset-font-size);\n border: 1px solid var(--md-default-fg-color);\n border-bottom: none;\n border-collapse: collapse;\n border-radius: ${theme.shape.borderRadius}px;\n}\n.md-typeset table:not([class]) th {\n font-weight: bold;\n}\n.md-typeset table:not([class]) td, .md-typeset table:not([class]) th {\n border-bottom: 1px solid var(--md-default-fg-color);\n}\n\n.md-typeset pre > code::-webkit-scrollbar-thumb {\n background-color: hsla(0, 0%, 0%, 0.32);\n}\n.md-typeset pre > code::-webkit-scrollbar-thumb:hover {\n background-color: hsla(0, 0%, 0%, 0.87);\n}\n\n.md-typeset code {\n word-break: keep-all;\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 { RuleOptions } from './types';\nimport { Theme } from '@material-ui/core/styles';\n\nconst themeHashes: Record<Theme['palette']['type'], ReadonlyArray<string>> = {\n dark: ['#only-light', '#gh-light-mode-only'],\n light: ['#only-dark', '#gh-dark-mode-only'],\n};\n\nexport default ({ theme }: RuleOptions) => `\n/*================== Palette ==================*/\n/*\n When color palette toggle is enabled in material theme for Mkdocs, there is a possibility to show conditionally \n images by adding #only-dark or #only-light to resource hash. Backstage doesn't use mkdocs color palette mechanism,\n so there is a need to add css rules from palette*.css manually.\n*/\n\n${themeHashes[theme.palette.type]\n .map(hash => `img[src$=\"${hash}\"]`)\n .join(', ')} {\n display: none;\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 */\n\nimport { default as variables } from './variables';\nimport { default as reset } from './reset';\nimport { default as layout } from './layout';\nimport { default as typeset } from './typeset';\nimport { default as animations } from './animations';\nimport { default as extensions } from './extensions';\nimport palette from './palette';\n\n/**\n * A list of style rules that will be applied to an element in the order they were added.\n *\n * @remarks\n * The order of items is important, which means that a rule can override any other rule previously added to the list,\n * i.e. the rules will be applied from the first added to the last added.\n */\nexport const rules = [\n variables,\n reset,\n layout,\n typeset,\n animations,\n extensions,\n palette,\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 */\n\nimport { alpha, lighten } from '@material-ui/core/styles';\nimport { RuleOptions } from './types';\n\nexport default ({ theme }: RuleOptions) => `\n/*================== Variables ==================*/\n/*\n As the MkDocs output is rendered in shadow DOM, the CSS variable definitions on the root selector are not applied. Instead, they have to be applied on :host.\n As there is no way to transform the served main*.css yet (for example in the backend), we have to copy from main*.css and modify them.\n*/\n\n:host {\n /* FONT */\n --md-default-fg-color: ${theme.palette.text.primary};\n --md-default-fg-color--light: ${theme.palette.text.secondary};\n --md-default-fg-color--lighter: ${lighten(theme.palette.text.secondary, 0.7)};\n --md-default-fg-color--lightest: ${lighten(\n theme.palette.text.secondary,\n 0.3,\n )};\n\n /* BACKGROUND */\n --md-default-bg-color:${theme.palette.background.default};\n --md-default-bg-color--light: ${theme.palette.background.paper};\n --md-default-bg-color--lighter: ${lighten(\n theme.palette.background.paper,\n 0.7,\n )};\n --md-default-bg-color--lightest: ${lighten(\n theme.palette.background.paper,\n 0.3,\n )};\n\n /* PRIMARY */\n --md-primary-fg-color: ${theme.palette.primary.main};\n --md-primary-fg-color--light: ${theme.palette.primary.light};\n --md-primary-fg-color--dark: ${theme.palette.primary.dark};\n --md-primary-bg-color: ${theme.palette.primary.contrastText};\n --md-primary-bg-color--light: ${lighten(\n theme.palette.primary.contrastText,\n 0.7,\n )};\n\n /* ACCENT */\n --md-accent-fg-color: var(--md-primary-fg-color);\n --md-accent-fg-color--transparent: ${alpha(theme.palette.primary.main, 0.1)};\n --md-accent-bg-color: var(--md-primary-bg-color);\n --md-accent-bg-color--light: var(--md-primary-bg-color--light);\n\n /* SHADOW */\n --md-shadow-z1: ${theme.shadows[1]};\n --md-shadow-z2: ${theme.shadows[2]};\n --md-shadow-z3: ${theme.shadows[3]};\n\n /* EXTENSIONS */\n --md-admonition-fg-color: var(--md-default-fg-color);\n --md-admonition-bg-color: var(--md-default-bg-color);\n /* Admonitions and others are using SVG masks to define icons. These masks are defined as CSS variables. */\n --md-admonition-icon--note: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z\"/></svg>');\n --md-admonition-icon--abstract: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M4 5h16v2H4V5m0 4h16v2H4V9m0 4h16v2H4v-2m0 4h10v2H4v-2z\"/></svg>');\n --md-admonition-icon--info: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M13 9h-2V7h2m0 10h-2v-6h2m-1-9A10 10 0 002 12a10 10 0 0010 10 10 10 0 0010-10A10 10 0 0012 2z\"/></svg>');\n --md-admonition-icon--tip: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M17.55 11.2c-.23-.3-.5-.56-.76-.82-.65-.6-1.4-1.03-2.03-1.66C13.3 7.26 13 4.85 13.91 3c-.91.23-1.75.75-2.45 1.32-2.54 2.08-3.54 5.75-2.34 8.9.04.1.08.2.08.33 0 .22-.15.42-.35.5-.22.1-.46.04-.64-.12a.83.83 0 01-.15-.17c-1.1-1.43-1.28-3.48-.53-5.12C5.89 10 5 12.3 5.14 14.47c.04.5.1 1 .27 1.5.14.6.4 1.2.72 1.73 1.04 1.73 2.87 2.97 4.84 3.22 2.1.27 4.35-.12 5.96-1.6 1.8-1.66 2.45-4.32 1.5-6.6l-.13-.26c-.2-.46-.47-.87-.8-1.25l.05-.01m-3.1 6.3c-.28.24-.73.5-1.08.6-1.1.4-2.2-.16-2.87-.82 1.19-.28 1.89-1.16 2.09-2.05.17-.8-.14-1.46-.27-2.23-.12-.74-.1-1.37.18-2.06.17.38.37.76.6 1.06.76 1 1.95 1.44 2.2 2.8.04.14.06.28.06.43.03.82-.32 1.72-.92 2.27h.01z\"/></svg>');\n --md-admonition-icon--success: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2m-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\"/></svg>');\n --md-admonition-icon--question: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M15.07 11.25l-.9.92C13.45 12.89 13 13.5 13 15h-2v-.5c0-1.11.45-2.11 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41a2 2 0 00-2-2 2 2 0 00-2 2H8a4 4 0 014-4 4 4 0 014 4 3.2 3.2 0 01-.93 2.25M13 19h-2v-2h2M12 2A10 10 0 002 12a10 10 0 0010 10 10 10 0 0010-10c0-5.53-4.5-10-10-10z\"/></svg>');\n --md-admonition-icon--warning: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M13 14h-2v-4h2m0 8h-2v-2h2M1 21h22L12 2 1 21z\"/></svg>');\n --md-admonition-icon--failure: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M12 2c5.53 0 10 4.47 10 10s-4.47 10-10 10S2 17.53 2 12 6.47 2 12 2m3.59 5L12 10.59 8.41 7 7 8.41 10.59 12 7 15.59 8.41 17 12 13.41 15.59 17 17 15.59 13.41 12 17 8.41 15.59 7z\"/></svg>');\n --md-admonition-icon--danger: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M11.5 20l4.86-9.73H13V4l-5 9.73h3.5V20M12 2c2.75 0 5.1 1 7.05 2.95C21 6.9 22 9.25 22 12s-1 5.1-2.95 7.05C17.1 21 14.75 22 12 22s-5.1-1-7.05-2.95C3 17.1 2 14.75 2 12s1-5.1 2.95-7.05C6.9 3 9.25 2 12 2z\"/></svg>');\n --md-admonition-icon--bug: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M14 12h-4v-2h4m0 6h-4v-2h4m6-6h-2.81a5.985 5.985 0 00-1.82-1.96L17 4.41 15.59 3l-2.17 2.17a6.002 6.002 0 00-2.83 0L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8z\"/></svg>');\n --md-admonition-icon--example: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M7 13v-2h14v2H7m0 6v-2h14v2H7M7 7V5h14v2H7M3 8V5H2V4h2v4H3m-1 9v-1h3v4H2v-1h2v-.5H3v-1h1V17H2m2.25-7a.75.75 0 01.75.75c0 .2-.08.39-.21.52L3.12 13H5v1H2v-.92L4 11H2v-1h2.25z\"/></svg>');\n --md-admonition-icon--quote: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M14 17h3l2-4V7h-6v6h3M6 17h3l2-4V7H5v6h3l-2 4z\"/></svg>');\n --md-footnotes-icon: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.42L5.83 13H21V7h-2z\"/></svg>');\n --md-details-icon: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M8.59 16.58 13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42z\"/></svg>');\n --md-tasklist-icon: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M0 0h24v24H0z\" fill=\"none\"/><path d=\"M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z\"/></svg>');\n --md-tasklist-icon--checked: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M0 0h24v24H0z\" fill=\"none\"/><path d=\"M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\"/></svg>');\n --md-nav-icon--prev: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z\"/></svg>');\n --md-nav-icon--next: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M8.59 16.58 13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42z\"/></svg>');\n --md-toc-icon: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M3 9h14V7H3v2m0 4h14v-2H3v2m0 4h14v-2H3v2m16 0h2v-2h-2v2m0-10v2h2V7h-2m0 6h2v-2h-2v2z\"/></svg>');\n --md-clipboard-icon: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M19 21H8V7h11m0-2H8a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2m-3-4H4a2 2 0 0 0-2 2v14h2V3h12V1z\"/></svg>');\n --md-search-result-icon: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h7c-.41-.25-.8-.56-1.14-.9-.33-.33-.61-.7-.86-1.1H6V4h7v5h5v1.18c.71.16 1.39.43 2 .82V8l-6-6m6.31 16.9c1.33-2.11.69-4.9-1.4-6.22-2.11-1.33-4.91-.68-6.22 1.4-1.34 2.11-.69 4.89 1.4 6.22 1.46.93 3.32.93 4.79.02L22 23.39 23.39 22l-3.08-3.1m-3.81.1a2.5 2.5 0 0 1-2.5-2.5 2.5 2.5 0 0 1 2.5-2.5 2.5 2.5 0 0 1 2.5 2.5 2.5 2.5 0 0 1-2.5 2.5z\"/></svg>');\n --md-source-forks-icon: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M5 3.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0zm0 2.122a2.25 2.25 0 1 0-1.5 0v.878A2.25 2.25 0 0 0 5.75 8.5h1.5v2.128a2.251 2.251 0 1 0 1.5 0V8.5h1.5a2.25 2.25 0 0 0 2.25-2.25v-.878a2.25 2.25 0 1 0-1.5 0v.878a.75.75 0 0 1-.75.75h-4.5A.75.75 0 0 1 5 6.25v-.878zm3.75 7.378a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0zm3-8.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5z\"/></svg>');\n --md-source-repositories-icon: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 1 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 0 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5v-9zm10.5-1V9h-8c-.356 0-.694.074-1 .208V2.5a1 1 0 0 1 1-1h8zM5 12.25v3.25a.25.25 0 0 0 .4.2l1.45-1.087a.25.25 0 0 1 .3 0L8.6 15.7a.25.25 0 0 0 .4-.2v-3.25a.25.25 0 0 0-.25-.25h-3.5a.25.25 0 0 0-.25.25z\"/></svg>');\n --md-source-stars-icon: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.75.75 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25zm0 2.445L6.615 5.5a.75.75 0 0 1-.564.41l-3.097.45 2.24 2.184a.75.75 0 0 1 .216.664l-.528 3.084 2.769-1.456a.75.75 0 0 1 .698 0l2.77 1.456-.53-3.084a.75.75 0 0 1 .216-.664l2.24-2.183-3.096-.45a.75.75 0 0 1-.564-.41L8 2.694v.001z\"/></svg>');\n --md-source-version-icon: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M2.5 7.775V2.75a.25.25 0 0 1 .25-.25h5.025a.25.25 0 0 1 .177.073l6.25 6.25a.25.25 0 0 1 0 .354l-5.025 5.025a.25.25 0 0 1-.354 0l-6.25-6.25a.25.25 0 0 1-.073-.177zm-1.5 0V2.75C1 1.784 1.784 1 2.75 1h5.025c.464 0 .91.184 1.238.513l6.25 6.25a1.75 1.75 0 0 1 0 2.474l-5.026 5.026a1.75 1.75 0 0 1-2.474 0l-6.25-6.25A1.75 1.75 0 0 1 1 7.775zM6 5a1 1 0 1 0 0 2 1 1 0 0 0 0-2z\"/></svg>');\n --md-version-icon: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 320 512\"><!--! Font Awesome Free 6.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d=\"m310.6 246.6-127.1 128c-7.1 6.3-15.3 9.4-23.5 9.4s-16.38-3.125-22.63-9.375l-127.1-128C.224 237.5-2.516 223.7 2.438 211.8S19.07 192 32 192h255.1c12.94 0 24.62 7.781 29.58 19.75s3.12 25.75-6.08 34.85z\"/></svg>');\n \n --md-status--updated: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><title>cellphone-arrow-down</title><path d=\"M17,1H7A2,2 0 0,0 5,3V21A2,2 0 0,0 7,23H17A2,2 0 0,0 19,21V3A2,2 0 0,0 17,1M17,19H7V5H17V19M16,13H13V8H11V13H8L12,17L16,13Z\" /></svg>');\n --md-status: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M11 9h2V7h-2m1 13c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8m0-18A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2m-1 15h2v-6h-2v6Z\"/></svg>');\n --md-status--new: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"m23 12-2.44-2.78.34-3.68-3.61-.82-1.89-3.18L12 3 8.6 1.54 6.71 4.72l-3.61.81.34 3.68L1 12l2.44 2.78-.34 3.69 3.61.82 1.89 3.18L12 21l3.4 1.46 1.89-3.18 3.61-.82-.34-3.68L23 12m-10 5h-2v-2h2v2m0-4h-2V7h2v6Z\"/></svg>');\n --md-status--deprecated: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M9 3v1H4v2h1v13a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V6h1V4h-5V3H9m0 5h2v9H9V8m4 0h2v9h-2V8Z\"/></svg>');\n --md-status--encrypted: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M12 1 3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4m0 6c1.4 0 2.8 1.1 2.8 2.5V11c.6 0 1.2.6 1.2 1.3v3.5c0 .6-.6 1.2-1.3 1.2H9.2c-.6 0-1.2-.6-1.2-1.3v-3.5c0-.6.6-1.2 1.2-1.2V9.5C9.2 8.1 10.6 7 12 7m0 1.2c-.8 0-1.5.5-1.5 1.3V11h3V9.5c0-.8-.7-1.3-1.5-1.3Z\"/></svg>');\n}\n\n:host > * {\n /* CODE */\n --md-code-fg-color: ${theme.palette.text.primary};\n --md-code-bg-color: ${\n theme.palette.code?.background ?? theme.palette.background.paper\n };\n --md-code-hl-color: ${alpha(theme.palette.warning.main, 0.5)};\n --md-code-hl-color--light: var(--md-code-hl-color);\n --md-code-hl-keyword-color: ${\n theme.palette.type === 'dark'\n ? theme.palette.primary.light\n : theme.palette.primary.dark\n };\n --md-code-hl-function-color: ${\n theme.palette.type === 'dark'\n ? theme.palette.secondary.light\n : theme.palette.secondary.dark\n };\n --md-code-hl-string-color: ${\n theme.palette.type === 'dark'\n ? theme.palette.success.light\n : theme.palette.success.dark\n };\n --md-code-hl-number-color: ${\n theme.palette.type === 'dark'\n ? theme.palette.error.light\n : theme.palette.error.dark\n };\n --md-code-hl-constant-color: var(--md-code-hl-function-color);\n --md-code-hl-special-color: var(--md-code-hl-function-color);\n --md-code-hl-name-color: var(--md-code-fg-color);\n --md-code-hl-comment-color: var(--md-default-fg-color--light);\n --md-code-hl-generic-color: var(--md-default-fg-color--light);\n --md-code-hl-variable-color: var(--md-default-fg-color--light);\n --md-code-hl-operator-color: var(--md-default-fg-color--light);\n --md-code-hl-punctuation-color: var(--md-default-fg-color--light);\n\n /* TYPESET */\n --md-typeset-font-size: 1rem;\n --md-typeset-color: var(--md-default-fg-color);\n --md-typeset-a-color: ${theme.palette.link};\n --md-typeset-table-color: ${theme.palette.text.primary};\n --md-typeset-table-color--light: ${alpha(theme.palette.text.primary, 0.05)};\n --md-typeset-del-color: ${\n theme.palette.type === 'dark'\n ? alpha(theme.palette.error.dark, 0.5)\n : alpha(theme.palette.error.light, 0.5)\n };\n --md-typeset-ins-color: ${\n theme.palette.type === 'dark'\n ? alpha(theme.palette.success.dark, 0.5)\n : alpha(theme.palette.success.light, 0.5)\n };\n --md-typeset-mark-color: ${\n theme.palette.type === 'dark'\n ? alpha(theme.palette.warning.dark, 0.5)\n : alpha(theme.palette.warning.light, 0.5)\n };\n --md-typeset-kbd-color: var(--md-code-bg-color);\n --md-typeset-kbd-accent-color var(--md-code-bg-color);\n --md-typeset-kbd-border-color: var(--md-default-fg-color--light);\n}\n\n@media screen and (max-width: 76.1875em) {\n :host > * {\n /* TYPESET */\n --md-typeset-font-size: .9rem;\n }\n}\n\n@media screen and (max-width: 600px) {\n :host > * {\n /* TYPESET */\n --md-typeset-font-size: .7rem;\n }\n}\n\n --md-footer-bg-color: var(--md-default-bg-color);\n --md-footer-bg-color--dark: var(--md-default-bg-color);\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 */\n\nimport { RuleOptions } from './types';\n\nexport default ({ theme }: RuleOptions) => `\n/*================== Reset ==================*/\n\nbody {\n --md-text-color: var(--md-default-fg-color);\n --md-text-link-color: var(--md-accent-fg-color);\n --md-text-font-family: ${theme.typography.fontFamily};\n font-family: var(--md-text-font-family);\n background-color: unset;\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 */\n\nimport { RuleOptions } from './types';\n\nconst SIDEBAR_WIDTH = '224px';\n\nexport default ({ theme, sidebar }: RuleOptions) => `\n\n/*================== Layout ==================*/\n\n/* mkdocs material v9 compat */\n.md-nav__title {\n color: var(--md-default-fg-color);\n}\n\n.md-grid {\n max-width: 100%;\n margin: 0;\n}\n\n.md-nav {\n font-size: calc(var(--md-typeset-font-size) * 0.9);\n}\n.md-nav__link:not(:has(svg)) {\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n.md-nav__link:has(svg) > .md-ellipsis {\n flex-grow: 1;\n}\n.md-nav__icon {\n height: 20px !important;\n width: 20px !important;\n margin-left:${theme.spacing(1)}px;\n}\n.md-nav__icon svg {\n margin: 0;\n width: 20px !important;\n height: 20px !important;\n}\n.md-nav__icon:after {\n width: 20px !important;\n height: 20px !important;\n}\n.md-status--updated::after {\n -webkit-mask-image: var(--md-status--updated);\n mask-image: var(--md-status--updated);\n}\n\n.md-nav__item--active > .md-nav__link, a.md-nav__link--active {\n text-decoration: underline;\n color: var(--md-typeset-a-color);\n}\n.md-nav__link--active > .md-status:after {\n background-color: var(--md-typeset-a-color);\n}\n.md-nav__link[href]:hover > .md-status:after {\n background-color: var(--md-accent-fg-color);\n}\n\n.md-main__inner {\n margin-top: 0;\n}\n\n.md-sidebar {\n bottom: 75px;\n position: fixed;\n width: 16rem;\n overflow-y: auto;\n overflow-x: hidden;\n scrollbar-color: rgb(193, 193, 193) #eee;\n scrollbar-width: thin;\n}\n.md-sidebar .md-sidebar__scrollwrap {\n width: calc(16rem);\n overflow-y: hidden;\n}\n@supports selector(::-webkit-scrollbar) {\n [dir=ltr] .md-sidebar__inner {\n padding-right: calc(100% - 15.1rem);\n }\n}\n.md-sidebar--secondary {\n right: ${theme.spacing(3)}px;\n}\n.md-sidebar::-webkit-scrollbar {\n width: 5px;\n}\n.md-sidebar::-webkit-scrollbar-button {\n width: 5px;\n height: 5px;\n}\n.md-sidebar::-webkit-scrollbar-track {\n background: #eee;\n border: 1 px solid rgb(250, 250, 250);\n box-shadow: 0px 0px 3px #dfdfdf inset;\n border-radius: 3px;\n}\n.md-sidebar::-webkit-scrollbar-thumb {\n width: 5px;\n background: rgb(193, 193, 193);\n border: transparent;\n border-radius: 3px;\n}\n.md-sidebar::-webkit-scrollbar-thumb:hover {\n background: rgb(125, 125, 125);\n}\n\n.md-content {\n max-width: calc(100% - 16rem * 2);\n margin-left: 16rem;\n margin-bottom: 50px;\n}\n\n.md-content > .md-sidebar {\n left: 16rem;\n}\n\n.md-footer {\n position: fixed;\n bottom: 0px;\n pointer-events: none;\n}\n\n.md-footer-nav__link, .md-footer__link {\n pointer-events: all;\n}\n\n.md-footer__title {\n background-color: unset;\n}\n.md-footer-nav__link, .md-footer__link {\n width: 16rem;\n}\n\n.md-dialog {\n background-color: unset;\n}\n\n@media screen and (min-width: 76.25em) {\n .md-sidebar {\n height: auto;\n }\n}\n\n@media screen and (max-width: 76.1875em) {\n .md-nav {\n transition: none !important;\n background-color: var(--md-default-bg-color)\n }\n .md-nav--primary .md-nav__title {\n cursor: auto;\n color: var(--md-default-fg-color);\n font-weight: 700;\n white-space: normal;\n line-height: 1rem;\n height: auto;\n display: flex;\n flex-flow: column;\n row-gap: 1.6rem;\n padding: 1.2rem .8rem .8rem;\n background-color: var(--md-default-bg-color);\n }\n .md-nav--primary .md-nav__title~.md-nav__list {\n box-shadow: none;\n }\n .md-nav--primary .md-nav__title ~ .md-nav__list > :first-child {\n border-top: none;\n }\n .md-nav--primary .md-nav__title .md-nav__button {\n display: none;\n }\n .md-nav--primary .md-nav__title .md-nav__icon {\n color: var(--md-default-fg-color);\n position: static;\n height: auto;\n margin: 0 0 0 -0.2rem;\n }\n .md-nav--primary > .md-nav__title [for=\"none\"] {\n padding-top: 0;\n }\n .md-nav--primary .md-nav__item {\n border-top: none;\n }\n .md-nav--primary :is(.md-nav__title,.md-nav__item) {\n font-size : var(--md-typeset-font-size);\n }\n .md-nav .md-source {\n display: none;\n }\n\n .md-sidebar {\n height: 100%;\n }\n .md-sidebar--primary {\n width: 16rem !important;\n z-index: 200;\n left: ${\n sidebar.isPinned\n ? `calc(-16rem + ${SIDEBAR_WIDTH})`\n : 'calc(-16rem + 72px)'\n } !important;\n }\n .md-sidebar--secondary:not([hidden]) {\n display: none;\n }\n\n [data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary {\n transform: translateX(16rem);\n }\n\n .md-content {\n max-width: 100%;\n margin-left: 0;\n }\n\n .md-header__button {\n margin: 0.4rem 0;\n margin-left: 0.4rem;\n padding: 0;\n }\n\n .md-overlay {\n left: 0;\n }\n\n .md-footer {\n position: static;\n padding-left: 0;\n }\n .md-footer-nav__link {\n /* footer links begin to overlap at small sizes without setting width */\n width: 50%;\n }\n}\n\n@media screen and (max-width: 600px) {\n .md-sidebar--primary {\n left: -16rem !important;\n width: 16rem;\n }\n}\n\n\n@media print {\n .md-sidebar,\n #toggle-sidebar {\n display: none;\n }\n\n .md-content {\n margin: 0;\n width: 100%;\n max-width: 100%;\n }\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 */\n\nexport default () => `\n/*================== Animations ==================*/\n/*\n Disable CSS animations on link colors as they lead to issues in dark mode.\n The dark mode color theme is applied later and theirfore there is always an animation from light to dark mode when navigation between pages.\n*/\n.md-dialog, .md-nav__link, .md-footer__link, .md-typeset a, .md-typeset a::before, .md-typeset .headerlink {\n transition: none;\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 */\n\nimport { RuleOptions } from './types';\n\nexport default ({ theme }: RuleOptions) => `\n/*================== Extensions ==================*/\n\n/* HIGHLIGHT */\n.highlight .md-clipboard:after {\n content: unset;\n}\n\n.highlight .nx {\n color: ${theme.palette.type === 'dark' ? '#ff53a3' : '#ec407a'};\n}\n\n/* CODE HILITE */\n.codehilite .gd {\n background-color: ${\n theme.palette.type === 'dark' ? 'rgba(248,81,73,0.65)' : '#fdd'\n };\n}\n\n.codehilite .gi {\n background-color: ${\n theme.palette.type === 'dark' ? 'rgba(46,160,67,0.65)' : '#dfd'\n };\n}\n\n/* TABBED */\n.tabbed-set>input:nth-child(1):checked~.tabbed-labels>:nth-child(1),\n.tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),\n.tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),\n.tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),\n.tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),\n.tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),\n.tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),\n.tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),\n.tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9),\n.tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),\n.tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),\n.tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),\n.tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),\n.tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),\n.tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),\n.tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),\n.tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),\n.tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),\n.tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),\n.tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20) {\n color: var(--md-accent-fg-color);\n border-color: var(--md-accent-fg-color);\n}\n\n/* TASK-LIST */\n.task-list-control .task-list-indicator::before {\n background-color: ${theme.palette.action.disabledBackground};\n}\n.task-list-control [type=\"checkbox\"]:checked + .task-list-indicator:before {\n background-color: ${theme.palette.success.main};\n}\n\n/* ADMONITION */\n.admonition {\n font-size: var(--md-typeset-font-size) !important;\n}\n.admonition .admonition-title {\n padding-left: 2.5rem !important;\n}\n\n.admonition .admonition-title:before {\n top: 50% !important;\n width: 20px !important;\n height: 20px !important;\n transform: translateY(-50%) !important;\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\nexport type Transformer = (dom: Element) => Element | Promise<Element>;\n\nexport const transform = async (\n html: string | Element,\n transformers: Transformer[],\n): Promise<Element> => {\n let dom: Element;\n\n if (typeof html === 'string') {\n dom = new DOMParser().parseFromString(html, 'text/html').documentElement;\n } else if (html instanceof Element) {\n dom = html;\n } else {\n throw new Error('dom is not a recognized type');\n }\n\n for (const transformer of transformers) {\n dom = await transformer(dom);\n }\n\n return dom;\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 */\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport { TechDocsStorageApi } from '../../api';\nimport type { Transformer } from './transformer';\n\ntype AddBaseUrlOptions = {\n techdocsStorageApi: TechDocsStorageApi;\n entityId: CompoundEntityRef;\n path: string;\n};\n\n/**\n * TechDocs backend serves SVGs with text/plain content-type for security. This\n * helper determines if an SVG is being loaded from the backend, and thus needs\n * inlining to be displayed properly.\n */\nconst isSvgNeedingInlining = (\n attrName: string,\n attrVal: string,\n apiOrigin: string,\n) => {\n // Let's let the URL object do automatic parsing of the pathname for us\n const pathname = new URL(attrVal, 'https://ignored.com').pathname;\n const isSrcToSvg = attrName === 'src' && pathname.endsWith('.svg');\n\n const isRelativeUrl = !attrVal.match(/^([a-z]*:)?\\/\\//i);\n const pointsToOurBackend = attrVal.startsWith(apiOrigin);\n return isSrcToSvg && (isRelativeUrl || pointsToOurBackend);\n};\n\nexport const addBaseUrl = ({\n techdocsStorageApi,\n entityId,\n path,\n}: AddBaseUrlOptions): Transformer => {\n return async dom => {\n const apiOrigin = await techdocsStorageApi.getApiOrigin();\n\n const updateDom = async <T extends Element>(\n list: HTMLCollectionOf<T> | NodeListOf<T>,\n attributeName: string,\n ) => {\n for (const elem of list) {\n if (elem.hasAttribute(attributeName)) {\n const elemAttribute = elem.getAttribute(attributeName);\n if (!elemAttribute) return;\n\n // Special handling for SVG images.\n const newValue = await techdocsStorageApi.getBaseUrl(\n elemAttribute,\n entityId,\n path,\n );\n\n if (isSvgNeedingInlining(attributeName, elemAttribute, apiOrigin)) {\n try {\n const svg = await fetch(newValue, { credentials: 'include' });\n const svgContent = await svg.text();\n elem.setAttribute(\n attributeName,\n `data:image/svg+xml;base64,${btoa(\n unescape(encodeURIComponent(svgContent)),\n )}`,\n );\n } catch (e) {\n elem.setAttribute('alt', `Error: ${elemAttribute}`);\n }\n } else {\n elem.setAttribute(attributeName, newValue);\n }\n }\n }\n };\n\n await Promise.all([\n updateDom<HTMLImageElement>(dom.querySelectorAll('img'), 'src'),\n updateDom<HTMLScriptElement>(dom.querySelectorAll('script'), 'src'),\n updateDom<HTMLSourceElement>(dom.querySelectorAll('source'), 'src'),\n updateDom<HTMLLinkElement>(dom.querySelectorAll('link'), 'href'),\n updateDom<HTMLAnchorElement>(dom.querySelectorAll('a[download]'), 'href'),\n ]);\n\n return dom;\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 type { Transformer } from './transformer';\n\nexport const rewriteDocLinks = (): Transformer => {\n return dom => {\n const updateDom = <T extends Element>(\n list: Array<T>,\n attributeName: string,\n ): void => {\n Array.from(list)\n .filter(elem => elem.hasAttribute(attributeName))\n .forEach((elem: T) => {\n const elemAttribute = elem.getAttribute(attributeName);\n if (elemAttribute) {\n // if link is external, add target to open in a new window or tab\n if (elemAttribute.match(/^https?:\\/\\//i)) {\n elem.setAttribute('target', '_blank');\n }\n\n try {\n const normalizedWindowLocation = normalizeUrl(\n window.location.href,\n );\n elem.setAttribute(\n attributeName,\n new URL(elemAttribute, normalizedWindowLocation).toString(),\n );\n } catch (_e) {\n // Non-parseable links should be re-written as plain text.\n elem.replaceWith(elem.textContent || elemAttribute);\n }\n }\n });\n };\n\n updateDom(Array.from(dom.getElementsByTagName('a')), 'href');\n\n return dom;\n };\n};\n\n/** Make sure that the input url always ends with a '/' */\nexport function normalizeUrl(input: string): string {\n const url = new URL(input);\n\n if (!url.pathname.endsWith('/') && !url.pathname.endsWith('.html')) {\n url.pathname += '/';\n }\n\n return url.toString();\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 { makeStyles } from '@material-ui/core/styles';\nimport { useState } from 'react';\nimport Snackbar from '@material-ui/core/Snackbar';\nimport Button from '@material-ui/core/Button';\n\ntype TechDocsRedirectNotificationProps = {\n handleButtonClick: () => void;\n message: string;\n autoHideDuration: number;\n};\n\nconst useStyles = makeStyles(theme => ({\n button: {\n color: theme.palette.primary.light,\n textDecoration: 'underline',\n },\n}));\n\nexport const TechDocsRedirectNotification = ({\n message,\n handleButtonClick,\n autoHideDuration,\n}: TechDocsRedirectNotificationProps) => {\n const classes = useStyles();\n const [open, setOpen] = useState(true);\n\n const handleClose = () => setOpen(false);\n\n return (\n <Snackbar\n open={open}\n anchorOrigin={{ vertical: 'top', horizontal: 'right' }}\n autoHideDuration={autoHideDuration}\n color=\"primary\"\n onClose={handleClose}\n message={message}\n action={\n <Button\n classes={{ root: classes.button }}\n size=\"small\"\n onClick={() => {\n handleClose();\n handleButtonClick();\n }}\n >\n Redirect now\n </Button>\n }\n />\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 */\n\nimport { useState, useCallback } from 'react';\nimport { renderReactElement } from './renderReactElement';\nimport { ThemeProvider } from '@material-ui/core/styles';\nimport SvgIcon from '@material-ui/core/SvgIcon';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport { withStyles, Theme } from '@material-ui/core/styles';\nimport IconButton from '@material-ui/core/IconButton';\nimport type { Transformer } from './transformer';\nimport useCopyToClipboard from 'react-use/esm/useCopyToClipboard';\n\nconst CopyToClipboardTooltip = withStyles(theme => ({\n tooltip: {\n fontSize: 'inherit',\n color: theme.palette.text.primary,\n margin: 0,\n padding: theme.spacing(0.5),\n backgroundColor: 'transparent',\n boxShadow: 'none',\n },\n}))(Tooltip);\n\nconst CopyToClipboardIcon = () => (\n <SvgIcon>\n <path d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\" />\n </SvgIcon>\n);\n\ntype CopyToClipboardButtonProps = {\n text: string;\n};\n\nconst CopyToClipboardButton = ({ text }: CopyToClipboardButtonProps) => {\n const [open, setOpen] = useState(false);\n const [, copyToClipboard] = useCopyToClipboard();\n\n const handleClick = useCallback(() => {\n copyToClipboard(text);\n setOpen(true);\n }, [text, copyToClipboard]);\n\n const handleClose = useCallback(() => {\n setOpen(false);\n }, [setOpen]);\n\n return (\n <CopyToClipboardTooltip\n title=\"Copied to clipboard\"\n placement=\"left\"\n open={open}\n onClose={handleClose}\n leaveDelay={1000}\n >\n <IconButton\n style={{ position: 'absolute' }}\n className=\"md-clipboard md-icon\"\n onClick={handleClick}\n aria-label=\"Copy to clipboard\"\n >\n <CopyToClipboardIcon />\n </IconButton>\n </CopyToClipboardTooltip>\n );\n};\n\n/**\n * Recreates copy-to-clipboard functionality attached to <code> snippets that\n * is native to mkdocs-material theme.\n */\nexport const copyToClipboard = (theme: Theme): Transformer => {\n return dom => {\n const codes = dom.querySelectorAll('pre > code');\n for (const code of codes) {\n const text = code.textContent || '';\n const container = document.createElement('div');\n code?.parentElement?.prepend(container);\n renderReactElement(\n <ThemeProvider theme={theme}>\n <CopyToClipboardButton text={text} />\n </ThemeProvider>,\n container,\n );\n }\n return dom;\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 { SHADOW_DOM_STYLE_LOAD_EVENT } from '@backstage/plugin-techdocs-react';\nimport type { Transformer } from './transformer';\n\ntype OnCssReadyOptions = {\n onLoading: () => void;\n onLoaded: () => void;\n};\n\nexport const onCssReady = ({\n onLoading,\n onLoaded,\n}: OnCssReadyOptions): Transformer => {\n return dom => {\n onLoading();\n dom.addEventListener(\n SHADOW_DOM_STYLE_LOAD_EVENT,\n function handleShadowDomStyleLoad() {\n onLoaded();\n dom.removeEventListener(\n SHADOW_DOM_STYLE_LOAD_EVENT,\n handleShadowDomStyleLoad,\n );\n },\n );\n return dom;\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 */\n\nimport Portal from '@material-ui/core/Portal';\nimport {\n useTechDocsAddons,\n TechDocsAddonLocations as locations,\n useTechDocsReaderPage,\n} from '@backstage/plugin-techdocs-react';\n\nexport const TechDocsReaderPageContentAddons = () => {\n const addons = useTechDocsAddons();\n\n const { shadowRoot } = useTechDocsReaderPage();\n\n const contentElement = shadowRoot?.querySelector(\n '[data-md-component=\"content\"]',\n );\n\n const primarySidebarElement = shadowRoot?.querySelector(\n 'div[data-md-component=\"sidebar\"][data-md-type=\"navigation\"], div[data-md-component=\"navigation\"]',\n );\n let primarySidebarAddonLocation = primarySidebarElement?.querySelector(\n '[data-techdocs-addons-location=\"primary sidebar\"]',\n );\n if (!primarySidebarAddonLocation) {\n primarySidebarAddonLocation = document.createElement('div');\n primarySidebarAddonLocation.setAttribute(\n 'data-techdocs-addons-location',\n 'primary sidebar',\n );\n primarySidebarElement?.prepend(primarySidebarAddonLocation);\n }\n\n const secondarySidebarElement = shadowRoot?.querySelector(\n 'div[data-md-component=\"sidebar\"][data-md-type=\"toc\"], div[data-md-component=\"toc\"]',\n );\n let secondarySidebarAddonLocation = secondarySidebarElement?.querySelector(\n '[data-techdocs-addons-location=\"secondary sidebar\"]',\n );\n if (!secondarySidebarAddonLocation) {\n secondarySidebarAddonLocation = document.createElement('div');\n secondarySidebarAddonLocation.setAttribute(\n 'data-techdocs-addons-location',\n 'secondary sidebar',\n );\n secondarySidebarElement?.prepend(secondarySidebarAddonLocation);\n }\n\n return (\n <>\n <Portal container={primarySidebarAddonLocation}>\n {addons.renderComponentsByLocation(locations.PrimarySidebar)}\n </Portal>\n <Portal container={contentElement}>\n {addons.renderComponentsByLocation(locations.Content)}\n </Portal>\n <Portal container={secondarySidebarAddonLocation}>\n {addons.renderComponentsByLocation(locations.SecondarySidebar)}\n </Portal>\n </>\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 */\n\nimport { useCallback, useEffect } from 'react';\n\nimport Grid from '@material-ui/core/Grid';\nimport { makeStyles } from '@material-ui/core/styles';\n\nimport {\n TechDocsShadowDom,\n useShadowDomStylesLoading,\n useShadowRootElements,\n useTechDocsReaderPage,\n} from '@backstage/plugin-techdocs-react';\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport { Content, Progress } from '@backstage/core-components';\n\nimport { TechDocsSearch } from '../../../search';\nimport { TechDocsStateIndicator } from '../TechDocsStateIndicator';\n\nimport { useTechDocsReaderDom } from './dom';\nimport {\n useTechDocsReader,\n withTechDocsReaderProvider,\n} from '../TechDocsReaderProvider';\nimport { TechDocsReaderPageContentAddons } from './TechDocsReaderPageContentAddons';\nimport { useApp } from '@backstage/core-plugin-api';\n\nconst useStyles = makeStyles({\n search: {\n width: '100%',\n '@media (min-width: 76.1875em)': {\n width: 'calc(100% - 34.4rem)',\n margin: '0 auto',\n },\n '@media print': {\n display: 'none',\n },\n },\n});\n\n/**\n * Props for {@link TechDocsReaderPageContent}\n * @public\n */\nexport type TechDocsReaderPageContentProps = {\n /**\n * @deprecated No need to pass down entityRef as property anymore. Consumes the entityName from `TechDocsReaderPageContext`. Use the {@link @backstage/plugin-techdocs-react#useTechDocsReaderPage} hook for custom reader page content.\n */\n entityRef?: CompoundEntityRef;\n /**\n * Path in the docs to render by default. This should be used when rendering docs for an entity that specifies the\n * \"backstage.io/techdocs-entity-path\" annotation for deep linking into another entities docs.\n */\n defaultPath?: string;\n /**\n * Show or hide the search bar, defaults to true.\n */\n withSearch?: boolean;\n /**\n * If {@link TechDocsReaderPageContentProps.withSearch | withSearch} is true,\n * this will redirect the search result urls, e.g. turn search results into\n * links within the \"Docs\" tab of the entity page, instead of the global docs\n * page.\n */\n searchResultUrlMapper?: (url: string) => string;\n /**\n * Callback called when the content is rendered.\n */\n onReady?: () => void;\n};\n\n/**\n * Renders the reader page content\n * @public\n */\nexport const TechDocsReaderPageContent = withTechDocsReaderProvider(\n (props: TechDocsReaderPageContentProps) => {\n const { withSearch = true, searchResultUrlMapper, onReady } = props;\n const classes = useStyles();\n\n const {\n entityMetadata: { value: entityMetadata, loading: entityMetadataLoading },\n entityRef,\n setShadowRoot,\n } = useTechDocsReaderPage();\n const { state } = useTechDocsReader();\n const dom = useTechDocsReaderDom(entityRef, props.defaultPath);\n const path = window.location.pathname;\n const hash = window.location.hash;\n const isStyleLoading = useShadowDomStylesLoading(dom);\n const [hashElement] = useShadowRootElements([`[id=\"${hash.slice(1)}\"]`]);\n const app = useApp();\n const { NotFoundErrorPage } = app.getComponents();\n\n useEffect(() => {\n if (isStyleLoading) return;\n\n if (hash) {\n if (hashElement) {\n hashElement.scrollIntoView();\n }\n } else {\n document?.querySelector('header')?.scrollIntoView();\n }\n }, [path, hash, hashElement, isStyleLoading]);\n\n const handleAppend = useCallback(\n (newShadowRoot: ShadowRoot) => {\n setShadowRoot(newShadowRoot);\n if (onReady instanceof Function) {\n onReady();\n }\n },\n [setShadowRoot, onReady],\n );\n\n // No entity metadata = 404. Don't render content at all.\n if (entityMetadataLoading === false && !entityMetadata)\n return <NotFoundErrorPage />;\n\n // Do not return content until dom is ready; instead, render a state\n // indicator, which handles progress and content errors on our behalf.\n if (!dom) {\n return (\n <Content>\n <Grid container>\n <Grid xs={12} item>\n <TechDocsStateIndicator />\n </Grid>\n </Grid>\n </Content>\n );\n }\n\n return (\n <Content>\n <Grid container>\n <Grid xs={12} item>\n <TechDocsStateIndicator />\n </Grid>\n {withSearch && (\n <Grid className={classes.search} xs=\"auto\" item>\n <TechDocsSearch\n entityId={entityRef}\n entityTitle={entityMetadata?.metadata?.title}\n searchResultUrlMapper={searchResultUrlMapper}\n />\n </Grid>\n )}\n <Grid xs={12} item>\n {/* Centers the styles loaded event to avoid having multiple locations setting the opacity style in Shadow Dom causing the screen to flash multiple times */}\n {(state === 'CHECKING' || isStyleLoading) && <Progress />}\n\n <TechDocsShadowDom element={dom} onAppend={handleAppend}>\n <TechDocsReaderPageContentAddons />\n </TechDocsShadowDom>\n </Grid>\n </Grid>\n </Content>\n );\n },\n);\n\n/**\n * Props for {@link Reader}\n *\n * @public\n * @deprecated use `TechDocsReaderPageContentProps` instead.\n */\nexport type ReaderProps = TechDocsReaderPageContentProps;\n\n/**\n * Component responsible for rendering TechDocs documentation\n * @public\n * @deprecated use `TechDocsReaderPageContent` component instead.\n */\nexport const Reader = TechDocsReaderPageContent;\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 */\n\nimport {\n useCallback,\n useEffect,\n useLayoutEffect,\n // useRef,\n useState,\n} from 'react';\n\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport { useTheme } from '@material-ui/core/styles';\n\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport { configApiRef, useAnalytics, useApi } from '@backstage/core-plugin-api';\nimport { scmIntegrationsApiRef } from '@backstage/integration-react';\n\nimport {\n techdocsStorageApiRef,\n useShadowDomStylesLoading,\n} from '@backstage/plugin-techdocs-react';\n\nimport { useTechDocsReader } from '../TechDocsReaderProvider';\n\nimport {\n addBaseUrl,\n addGitFeedbackLink,\n addLinkClickListener,\n addSidebarToggle,\n onCssReady,\n removeMkdocsHeader,\n rewriteDocLinks,\n simplifyMkdocsFooter,\n scrollIntoNavigation,\n transform as transformer,\n copyToClipboard,\n useSanitizerTransformer,\n useStylesTransformer,\n handleMetaRedirects,\n addNavLinkKeyboardToggle,\n} from '../../transformers';\nimport { useNavigateUrl } from './useNavigateUrl';\nimport { useLocation, useNavigate, useParams } from 'react-router-dom';\n\nconst MOBILE_MEDIA_QUERY = 'screen and (max-width: 76.1875em)';\n\n// If a defaultPath is specified then we should navigate to that path replacing the\n// current location in the history. This should only happen on the initial load so\n// navigating to the root of the docs doesn't also redirect.\nexport const useInitialRedirect = (defaultPath?: string) => {\n const location = useLocation();\n const navigate = useNavigate();\n const { '*': currPath = '' } = useParams();\n\n useLayoutEffect(() => {\n if (currPath === '' && defaultPath) {\n navigate(`${location.pathname}${defaultPath}`, { replace: true });\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n};\n\n/**\n * Hook that encapsulates the behavior of getting raw HTML and applying\n * transforms to it in order to make it function at a basic level in the\n * Backstage UI.\n */\nexport const useTechDocsReaderDom = (\n entityRef: CompoundEntityRef,\n defaultPath?: string,\n): Element | null => {\n const navigate = useNavigateUrl();\n const theme = useTheme();\n const isMobileMedia = useMediaQuery(MOBILE_MEDIA_QUERY);\n const sanitizerTransformer = useSanitizerTransformer();\n const stylesTransformer = useStylesTransformer();\n const analytics = useAnalytics();\n\n const techdocsStorageApi = useApi(techdocsStorageApiRef);\n const scmIntegrationsApi = useApi(scmIntegrationsApiRef);\n const configApi = useApi(configApiRef);\n\n const { state, path, content: rawPage } = useTechDocsReader();\n const { '*': currPath = '' } = useParams();\n\n const [dom, setDom] = useState<HTMLElement | null>(null);\n const isStyleLoading = useShadowDomStylesLoading(dom);\n\n useInitialRedirect(defaultPath);\n\n const updateSidebarPositionAndHeight = useCallback(() => {\n if (!dom) return;\n\n const sidebars = dom.querySelectorAll<HTMLElement>('.md-sidebar');\n\n sidebars.forEach(element => {\n // set sidebar position to render in correct position\n if (isMobileMedia) {\n element.style.top = '0px';\n } else {\n const page = document?.querySelector('.techdocs-reader-page');\n const pageTop = page?.getBoundingClientRect().top ?? 0;\n let domTop = dom.getBoundingClientRect().top ?? 0;\n\n const tabs = dom.querySelector('.md-container > .md-tabs');\n const tabsHeight = tabs?.getBoundingClientRect().height ?? 0;\n\n // the sidebars should not scroll beyond the total height of the header and tabs\n if (domTop < pageTop) {\n domTop = pageTop;\n }\n\n const scrollbarTopPx = Math.max(domTop, 0) + tabsHeight;\n\n element.style.top = `${scrollbarTopPx}px`;\n\n // set scrollbar height to ensure all links can be seen when content is small\n const footer = dom.querySelector('.md-container > .md-footer');\n // if no footer, fallback to using the bottom of the window\n const scrollbarEndPx =\n footer?.getBoundingClientRect().top ?? window.innerHeight;\n\n element.style.height = `${scrollbarEndPx - scrollbarTopPx}px`;\n }\n\n // show the sidebar only after updating its position\n element.style.setProperty('opacity', '1');\n });\n }, [dom, isMobileMedia]);\n\n useEffect(() => {\n window.addEventListener('resize', updateSidebarPositionAndHeight);\n window.addEventListener('scroll', updateSidebarPositionAndHeight, true);\n return () => {\n window.removeEventListener('resize', updateSidebarPositionAndHeight);\n window.removeEventListener(\n 'scroll',\n updateSidebarPositionAndHeight,\n true,\n );\n };\n }, [dom, updateSidebarPositionAndHeight]);\n\n // dynamically set width of footer to accommodate for pinning of the sidebar\n const updateFooterWidth = useCallback(() => {\n if (!dom) return;\n const footer = dom.querySelector<HTMLElement>('.md-footer');\n if (footer) {\n footer.style.width = `${dom.getBoundingClientRect().width}px`;\n }\n }, [dom]);\n\n useEffect(() => {\n window.addEventListener('resize', updateFooterWidth);\n return () => {\n window.removeEventListener('resize', updateFooterWidth);\n };\n }, [dom, updateFooterWidth]);\n\n // an update to \"state\" might lead to an updated UI so we include it as a trigger\n useEffect(() => {\n if (!isStyleLoading) {\n updateFooterWidth();\n updateSidebarPositionAndHeight();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n state,\n isStyleLoading,\n updateFooterWidth,\n updateSidebarPositionAndHeight,\n ]);\n\n // a function that performs transformations that are executed prior to adding it to the DOM\n const preRender = useCallback(\n (rawContent: string, contentPath: string) =>\n transformer(rawContent, [\n sanitizerTransformer,\n addBaseUrl({\n techdocsStorageApi,\n entityId: entityRef,\n path: contentPath,\n }),\n rewriteDocLinks(),\n addSidebarToggle(),\n removeMkdocsHeader(),\n simplifyMkdocsFooter(),\n addGitFeedbackLink(scmIntegrationsApi),\n stylesTransformer,\n ]),\n [\n // only add dependencies that are in state or memorized variables to avoid unnecessary calls between re-renders\n entityRef,\n scmIntegrationsApi,\n techdocsStorageApi,\n sanitizerTransformer,\n stylesTransformer,\n ],\n );\n\n // a function that performs transformations that are executed after adding it to the DOM\n const postRender = useCallback(\n async (transformedElement: Element) =>\n transformer(transformedElement, [\n handleMetaRedirects(navigate, entityRef.name),\n scrollIntoNavigation(),\n copyToClipboard(theme),\n addLinkClickListener({\n baseUrl:\n configApi.getOptionalString('app.baseUrl') ||\n window.location.origin,\n onClick: (event: MouseEvent, url: string) => {\n // detect if CTRL or META keys are pressed so that links can be opened in a new tab with `window.open`\n const modifierActive = event.ctrlKey || event.metaKey;\n const parsedUrl = new URL(url);\n\n // capture link clicks within documentation\n const linkText =\n (event.target as HTMLAnchorElement | undefined)?.innerText || url;\n const to = url.replace(window.location.origin, '');\n analytics.captureEvent('click', linkText, { attributes: { to } });\n\n // hash exists when anchor is clicked on secondary sidebar\n if (parsedUrl.hash) {\n if (modifierActive) {\n window.open(url, '_blank');\n } else {\n // If it's in a different page, we navigate to it\n if (window.location.pathname !== parsedUrl.pathname) {\n navigate(url);\n } else {\n // If it's in the same page we avoid using navigate that causes\n // the page to rerender.\n window.history.pushState(\n null,\n document.title,\n parsedUrl.hash,\n );\n }\n // Scroll to hash if it's on the current page\n transformedElement\n ?.querySelector(`[id=\"${parsedUrl.hash.slice(1)}\"]`)\n ?.scrollIntoView();\n\n // Focus first focusable element in the target section\n (\n transformedElement\n ?.querySelector(`[id=\"${parsedUrl.hash.slice(1)}\"]`)\n ?.querySelector('a, button, [tabindex]') as HTMLElement\n )?.focus();\n }\n } else {\n if (modifierActive) {\n window.open(url, '_blank');\n } else {\n navigate(url);\n }\n }\n },\n }),\n // disable MkDocs drawer toggling ('for' attribute => checkbox mechanism)\n onCssReady({\n onLoading: () => {},\n onLoaded: () => {\n transformedElement\n .querySelector('.md-nav__title')\n ?.removeAttribute('for');\n },\n }),\n // hide sidebars until their positions are updated\n onCssReady({\n onLoading: () => {\n const sidebars = Array.from(\n transformedElement.querySelectorAll<HTMLElement>('.md-sidebar'),\n );\n sidebars.forEach(element => {\n element.style.setProperty('opacity', '0');\n });\n },\n onLoaded: () => {},\n }),\n addNavLinkKeyboardToggle(),\n ]),\n [theme, navigate, analytics, entityRef.name, configApi],\n );\n\n useEffect(() => {\n if (!rawPage) return () => {};\n\n // if false, there is already a newer execution of this effect\n let shouldReplaceContent = true;\n\n // Pre-render\n preRender(rawPage, path).then(async preTransformedDomElement => {\n if (!preTransformedDomElement?.innerHTML) {\n return; // An unexpected error occurred\n }\n\n // don't manipulate the shadow dom if this isn't the latest effect execution\n if (!shouldReplaceContent) {\n return;\n }\n\n // Skip this update if the location's path has changed but the state\n // contains a page that isn't loaded yet.\n if (currPath !== path) {\n return;\n }\n\n // Scroll to top after render\n window.scroll({ top: 0 });\n\n // Post-render\n const postTransformedDomElement = await postRender(\n preTransformedDomElement,\n );\n\n setDom(postTransformedDomElement as HTMLElement);\n });\n\n // cancel this execution\n return () => {\n shouldReplaceContent = false;\n };\n }, [rawPage, currPath, path, preRender, postRender]);\n\n return dom;\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 { configApiRef, useApi } from '@backstage/core-plugin-api';\nimport { useCallback, useRef } from 'react';\nimport { useNavigate } from 'react-router-dom';\n\n/**\n * Resolve a URL to a relative URL given a base URL that may or may not include subpaths.\n * @param url - URL to parse into a relative url based on the baseUrl.\n * @param baseUrl - Application base url, where the application is currently hosted.\n * @returns relative path without any subpaths from website config.\n */\nexport function resolveUrlToRelative(url: string, baseUrl: string) {\n const parsedAppUrl = new URL(baseUrl);\n const appUrlPath = `${parsedAppUrl.origin}${parsedAppUrl.pathname.replace(\n /\\/$/,\n '',\n )}`;\n\n const relativeUrl = url\n .replace(appUrlPath, '')\n // Remove any leading slashes.\n .replace(/^\\/+/, '');\n const parsedUrl = new URL(`http://localhost/${relativeUrl}`);\n return `${parsedUrl.pathname}${parsedUrl.search}${parsedUrl.hash}`;\n}\n\n/**\n * A helper hook that allows for full internal website urls to be processed through the navigate\n * hook provided by `react-router-dom`.\n *\n * NOTE: This does not support routing to external URLs. That should be done with a `Link` or `a`\n * element instead, or just `window.location.href`.\n *\n * TODO: Update this to use `useRouteRef` instead of `useApi`.\n *\n * @returns Navigation function that is a wrapper over `react-router-dom`'s\n * to support passing full URLs for navigation.\n *\n * @public\n */\nexport function useNavigateUrl() {\n // useRef prevents useNavigate from causing unnecessary re-renders\n const navigate = useRef(useNavigate());\n const configApi = useApi(configApiRef);\n const appBaseUrl = configApi.getOptionalString('app.baseUrl');\n const navigateFn = useCallback(\n (to: string) => {\n let url = to;\n /**\n * This should always be true when running the application, this just allows\n * test cases that do not have the configApi set up to run still.\n */\n if (appBaseUrl) {\n try {\n url = resolveUrlToRelative(to, appBaseUrl);\n } catch (err) {\n // URL passed in was relative.\n }\n }\n navigate.current(url);\n },\n [appBaseUrl],\n );\n return navigateFn;\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 */\n\nimport DOMPurify from 'dompurify';\nimport { useCallback, useMemo } from 'react';\n\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { Transformer } from '../transformer';\nimport { removeUnsafeIframes, removeUnsafeLinks } from './hooks';\n\n/**\n * Returns html sanitizer configuration\n */\nconst useSanitizerConfig = () => {\n const configApi = useApi(configApiRef);\n\n return useMemo(() => {\n return configApi.getOptionalConfig('techdocs.sanitizer');\n }, [configApi]);\n};\n\n/**\n * Returns a transformer that sanitizes the dom\n */\nexport const useSanitizerTransformer = (): Transformer => {\n const config = useSanitizerConfig();\n\n return useCallback(\n async (dom: Element) => {\n const hosts = config?.getOptionalStringArray('allowedIframeHosts');\n\n DOMPurify.addHook('beforeSanitizeElements', removeUnsafeLinks);\n const tags = ['link', 'meta'];\n\n if (hosts) {\n tags.push('iframe');\n DOMPurify.addHook('beforeSanitizeElements', removeUnsafeIframes(hosts));\n }\n\n // Only allow meta tags if they are used for refreshing the page. They are required for the redirect feature.\n DOMPurify.addHook('uponSanitizeElement', (currNode, data) => {\n if (data.tagName === 'meta') {\n const isMetaRefreshTag =\n currNode.getAttribute('http-equiv') === 'refresh' &&\n currNode.getAttribute('content')?.includes('url=');\n if (!isMetaRefreshTag) {\n currNode.parentNode?.removeChild(currNode);\n }\n }\n });\n\n // Only allow http-equiv and content attributes on meta tags. They are required for the redirect feature.\n DOMPurify.addHook('uponSanitizeAttribute', (currNode, data) => {\n if (currNode.tagName !== 'meta') {\n if (data.attrName === 'http-equiv' || data.attrName === 'content') {\n currNode.removeAttribute(data.attrName);\n }\n }\n });\n\n const tagNameCheck = config?.getOptionalString(\n 'allowedCustomElementTagNameRegExp',\n );\n const attributeNameCheck = config?.getOptionalString(\n 'allowedCustomElementAttributeNameRegExp',\n );\n const additionalAllowedURIProtocols =\n config?.getOptionalStringArray('additionalAllowedURIProtocols') || [];\n\n // Define allowed URI protocols, including any additional ones from the config.\n // The default protocols are based on the DOMPurify defaults.\n const allowedURIProtocols = [\n 'callto',\n 'cid',\n 'ftp',\n 'ftps',\n 'http',\n 'https',\n 'mailto',\n 'matrix',\n 'sms',\n 'tel',\n 'xmpp',\n ...additionalAllowedURIProtocols,\n ].filter(Boolean);\n\n const allowedURIRegExp = new RegExp(\n // This regex is not exposed by DOMPurify, so we need to define it ourselves.\n // It is possible for this to drift from the default in future versions of DOMPurify.\n // See: https://raw.githubusercontent.com/cure53/DOMPurify/master/src/regexp.ts\n `^(?:${allowedURIProtocols.join(\n '|',\n )}:|[^a-z]|[a-z+.-]+(?:[^a-z+.\\\\-:]|$))`,\n 'i',\n );\n\n // using outerHTML as we want to preserve the html tag attributes (lang)\n return DOMPurify.sanitize(dom.outerHTML, {\n ADD_TAGS: tags,\n FORBID_TAGS: ['style'],\n ADD_ATTR: ['http-equiv', 'content', 'dominant-baseline'],\n WHOLE_DOCUMENT: true,\n RETURN_DOM: true,\n ALLOWED_URI_REGEXP: allowedURIRegExp,\n CUSTOM_ELEMENT_HANDLING: {\n tagNameCheck: tagNameCheck ? new RegExp(tagNameCheck) : undefined,\n attributeNameCheck: attributeNameCheck\n ? new RegExp(attributeNameCheck)\n : undefined,\n },\n });\n },\n [config],\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 */\n\n/**\n * Checks whether a node is iframe or not.\n * @param node - can be any element.\n * @returns true when node is iframe.\n */\nconst isIframe = (node: Element) => node.nodeName === 'IFRAME';\n\n/**\n * Checks whether a iframe is safe or not.\n * @param node - is an iframe element.\n * @param hosts - list of allowed hosts.\n * @returns true when iframe is included in hosts.\n */\nconst isSafe = (node: Element, hosts: string[]) => {\n const src = node.getAttribute('src') || '';\n try {\n const { host } = new URL(src);\n return hosts.includes(host);\n } catch {\n return false;\n }\n};\n\n/**\n * Returns a function that removes unsafe iframe nodes.\n * @param node - can be any element.\n * @param hosts - list of allowed hosts.\n */\nexport const removeUnsafeIframes = (hosts: string[]) => (node: Element) => {\n if (isIframe(node) && !isSafe(node, hosts)) {\n node.remove();\n }\n return node;\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 */\n\nimport { useCallback, useMemo } from 'react';\nimport { useTheme } from '@material-ui/core/styles';\nimport { useSidebarPinState } from '@backstage/core-components';\nimport { Transformer } from '../transformer';\nimport { rules } from './rules';\n\n/**\n * Sidebar pinned state to be used in computing style injections.\n */\nconst useSidebar = () => useSidebarPinState();\n\n/**\n * Process all rules and concatenate their definitions into a single style.\n * @returns a string containing all processed style definitions.\n */\nconst useRuleStyles = () => {\n const sidebar = useSidebar();\n const theme = useTheme();\n\n return useMemo(() => {\n const options = { theme, sidebar };\n return rules.reduce<string>((styles, rule) => styles + rule(options), '');\n }, [theme, sidebar]);\n};\n\n/**\n * Returns a transformer that inserts all style rules into the given element's head tag.\n */\nexport const useStylesTransformer = (): Transformer => {\n const styles = useRuleStyles();\n\n return useCallback(\n (dom: Element) => {\n dom\n .getElementsByTagName('head')[0]\n .insertAdjacentHTML('beforeend', `<style>${styles}</style>`);\n return dom;\n },\n [styles],\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 type { Transformer } from './transformer';\nimport MenuIcon from '@material-ui/icons/Menu';\nimport { createElement } from 'react';\nimport { renderReactElement } from './renderReactElement';\n\nexport const addSidebarToggle = (): Transformer => {\n return dom => {\n // attempting to use selectors that are more likely to be static as MkDocs updates over time\n const mkdocsToggleSidebar = dom.querySelector(\n '.md-header label[for=\"__drawer\"]',\n ) as HTMLLabelElement;\n const article = dom.querySelector('article') as HTMLElement;\n\n // Fail gracefully\n if (!mkdocsToggleSidebar || !article) {\n return dom;\n }\n\n const toggleSidebar = mkdocsToggleSidebar.cloneNode() as HTMLLabelElement;\n renderReactElement(createElement(MenuIcon), toggleSidebar);\n toggleSidebar.id = 'toggle-sidebar';\n toggleSidebar.title = 'Toggle Sidebar';\n toggleSidebar.classList.add('md-content__button');\n toggleSidebar.style.setProperty('padding', '0 0 0 5px');\n toggleSidebar.style.setProperty('margin', '0.4rem 0 0.4rem 0.4rem');\n article?.prepend(toggleSidebar);\n return dom;\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 type { Transformer } from './transformer';\n\nexport const removeMkdocsHeader = (): Transformer => {\n return dom => {\n // Remove the header\n dom.querySelector('.md-header')?.remove();\n\n return dom;\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 type { Transformer } from './transformer';\n\nexport const simplifyMkdocsFooter = (): Transformer => {\n return dom => {\n // Remove new mkdocs copyright\n dom.querySelector('.md-footer .md-copyright')?.remove();\n // Remove old mkdocs copyright\n dom.querySelector('.md-footer-copyright')?.remove();\n return dom;\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 type { Transformer } from './transformer';\nimport {\n replaceGithubUrlType,\n ScmIntegrationRegistry,\n} from '@backstage/integration';\nimport FeedbackOutlinedIcon from '@material-ui/icons/FeedbackOutlined';\nimport { createElement } from 'react';\nimport parseGitUrl from 'git-url-parse';\nimport { renderReactElement } from './renderReactElement';\n\n// requires repo\nexport const addGitFeedbackLink = (\n scmIntegrationsApi: ScmIntegrationRegistry,\n): Transformer => {\n return dom => {\n // attempting to use selectors that are more likely to be static as MkDocs updates over time\n const sourceAnchor = dom.querySelector(\n '[title=\"Edit this page\"]',\n ) as HTMLAnchorElement;\n\n // don't show if edit link not available in raw page\n if (!sourceAnchor || !sourceAnchor.href) {\n return dom;\n }\n\n const sourceURL = new URL(sourceAnchor.href);\n const integration = scmIntegrationsApi.byUrl(sourceURL);\n\n // don't show if can't identify edit link hostname as a gitlab/github hosting\n if (integration?.type !== 'github' && integration?.type !== 'gitlab') {\n return dom;\n }\n\n // topmost h1 only contains title for whole page\n const title =\n (dom.querySelector('article>h1') as HTMLElement)?.childNodes[0]\n .textContent || '';\n const issueTitle = encodeURIComponent(`Documentation Feedback: ${title}`);\n const issueDesc = encodeURIComponent(\n `Page source:\\n${sourceAnchor.href}\\n\\nFeedback:`,\n );\n\n // Convert GitHub edit url to blob type so it can be parsed by git-url-parse correctly\n const gitUrl =\n integration?.type === 'github'\n ? replaceGithubUrlType(sourceURL.href, 'blob')\n : sourceURL.href;\n const gitInfo = parseGitUrl(gitUrl);\n const repoPath = `/${gitInfo.organization}/${gitInfo.name}`;\n\n const feedbackLink = sourceAnchor.cloneNode() as HTMLAnchorElement;\n switch (integration?.type) {\n case 'gitlab':\n feedbackLink.href = `${sourceURL.origin}${repoPath}/issues/new?issue[title]=${issueTitle}&issue[description]=${issueDesc}`;\n break;\n case 'github':\n feedbackLink.href = `${sourceURL.origin}${repoPath}/issues/new?title=${issueTitle}&body=${issueDesc}`;\n break;\n default:\n return dom;\n }\n renderReactElement(createElement(FeedbackOutlinedIcon), feedbackLink);\n feedbackLink.style.paddingLeft = '5px';\n feedbackLink.title = 'Leave feedback for this page';\n feedbackLink.id = 'git-feedback-link';\n sourceAnchor?.insertAdjacentElement('beforebegin', feedbackLink);\n return dom;\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 { Transformer } from './transformer';\nimport { normalizeUrl } from './rewriteDocLinks';\nimport { renderReactElement } from './renderReactElement';\nimport { TechDocsRedirectNotification } from '../components/TechDocsRedirectNotification';\n\nexport const handleMetaRedirects = (\n navigate: (to: string) => void,\n entityName: string,\n): Transformer => {\n const redirectAfterMs = 3000;\n\n const determineRedirectURL = (metaUrl: string) => {\n const normalizedCurrentUrl = normalizeUrl(window.location.href);\n // When creating URL object, if the metaUrl is relative, it will be resolved with base href. If it is absolute, it will replace the base href.\n const absoluteRedirectObj = new URL(metaUrl, normalizedCurrentUrl);\n const isExternalRedirect =\n absoluteRedirectObj.hostname !== window.location.hostname;\n\n if (isExternalRedirect) {\n const currentTechDocPath = window.location.pathname;\n const indexOfSiteHome = currentTechDocPath.indexOf(entityName);\n const siteHomePath = currentTechDocPath.slice(\n 0,\n indexOfSiteHome + entityName.length,\n );\n return new URL(siteHomePath, normalizedCurrentUrl).href;\n }\n return absoluteRedirectObj.href;\n };\n\n return dom => {\n for (const elem of Array.from(dom.querySelectorAll('meta'))) {\n if (elem.getAttribute('http-equiv') === 'refresh') {\n const metaContentParameters = elem\n .getAttribute('content')\n ?.split('url=');\n\n if (!metaContentParameters || metaContentParameters.length < 2) {\n return dom;\n }\n\n const metaUrl = metaContentParameters[1];\n const redirectURL = determineRedirectURL(metaUrl);\n\n // If the current URL is the same as the redirect URL, do not proceed with the redirect.\n if (window.location.href === redirectURL) {\n return dom;\n }\n\n const container = document.createElement('div');\n\n renderReactElement(\n <TechDocsRedirectNotification\n message=\"This TechDocs page is no longer maintained. Will automatically redirect to the designated replacement.\"\n handleButtonClick={() => navigate(redirectURL)}\n autoHideDuration={redirectAfterMs}\n />,\n container,\n );\n document.body.appendChild(container);\n\n setTimeout(() => {\n navigate(redirectURL);\n }, redirectAfterMs);\n\n return dom;\n }\n }\n return dom;\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 type { Transformer } from './transformer';\n\nexport const scrollIntoNavigation = (): Transformer => {\n return dom => {\n setTimeout(() => {\n const activeNavItems = dom?.querySelectorAll(`li.md-nav__item--active`);\n if (activeNavItems.length !== 0) {\n // expand all navigation items that are active\n activeNavItems.forEach(activeNavItem => {\n const checkbox = activeNavItem?.querySelector('input');\n if (!checkbox?.checked) {\n checkbox?.click();\n }\n });\n\n const lastItem = activeNavItems[activeNavItems.length - 1];\n lastItem.scrollIntoView();\n }\n }, 200);\n return dom;\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 type { Transformer } from './transformer';\n\ntype AddLinkClickListenerOptions = {\n baseUrl: string;\n onClick: (e: MouseEvent, newUrl: string) => void;\n};\n\nexport const addLinkClickListener = ({\n baseUrl,\n onClick,\n}: AddLinkClickListenerOptions): Transformer => {\n return dom => {\n Array.from(dom.getElementsByTagName('a')).forEach(elem => {\n elem.addEventListener('click', (e: MouseEvent) => {\n const target = elem as HTMLAnchorElement;\n const href = target.getAttribute('href');\n\n if (!href) return;\n if (href.startsWith(baseUrl) && !elem.hasAttribute('download')) {\n e.preventDefault();\n onClick(e, href);\n }\n });\n });\n\n return dom;\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\nexport function addNavLinkKeyboardToggle() {\n return (element: Element) => {\n const navLabels = element.querySelectorAll('label.md-nav__link[for]');\n navLabels.forEach(label => {\n label.setAttribute('tabIndex', '0');\n label.addEventListener('keydown', event => {\n const keyboardEvent = event as KeyboardEvent;\n if (keyboardEvent.key === 'Enter' || keyboardEvent.key === ' ') {\n const forId = label.getAttribute('for');\n if (!forId) return;\n const checkbox = element.querySelector(\n `#${forId}`,\n ) as HTMLInputElement | null;\n if (checkbox && checkbox.type === 'checkbox') {\n checkbox.checked = !checkbox.checked;\n checkbox.dispatchEvent(new Event('change', { bubbles: true }));\n event.preventDefault();\n event.stopPropagation();\n }\n }\n });\n });\n return element;\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 { useEffect, useMemo, useState } from 'react';\nimport debounce from 'lodash/debounce';\nimport { useTechDocsReaderPage } from './context';\n\n/**\n * Hook for use within TechDocs addons that provides access to the underlying\n * shadow root of the current page, allowing the DOM within to be mutated.\n * @public\n */\nexport const useShadowRoot = () => {\n const { shadowRoot } = useTechDocsReaderPage();\n return shadowRoot;\n};\n\n/**\n * Convenience hook for use within TechDocs addons that provides access to\n * elements that match a given selector within the shadow root.\n *\n * @public\n */\nexport const useShadowRootElements = <\n TReturnedElement extends HTMLElement = HTMLElement,\n>(\n selectors: string[],\n): TReturnedElement[] => {\n const shadowRoot = useShadowRoot();\n const [root, setRootNode] = useState(shadowRoot?.firstChild);\n\n useEffect(() => {\n let observer: MutationObserver;\n if (shadowRoot) {\n observer = new MutationObserver(() => {\n setRootNode(shadowRoot?.firstChild);\n });\n observer.observe(shadowRoot, {\n attributes: true,\n characterData: true,\n childList: true,\n subtree: true,\n });\n }\n return () => observer?.disconnect();\n }, [shadowRoot]);\n\n if (!root || !(root instanceof HTMLElement)) return [];\n\n return selectors\n .map(selector => root.querySelectorAll<TReturnedElement>(selector))\n .filter(nodeList => nodeList.length)\n .map(nodeList => Array.from(nodeList))\n .flat();\n};\n\nconst isValidSelection = (newSelection: Selection) => {\n // Safari sets the selection rect to top zero\n return (\n newSelection.toString() &&\n newSelection.rangeCount &&\n newSelection.getRangeAt(0).getBoundingClientRect().top\n );\n};\n\n/**\n * Hook for retrieving a selection within the ShadowRoot.\n * @public\n */\nexport const useShadowRootSelection = (waitMillis: number = 0) => {\n const shadowRoot = useShadowRoot();\n const [selection, setSelection] = useState<Selection | null>(null);\n const handleSelectionChange = useMemo(\n () =>\n debounce(() => {\n const shadowDocument = shadowRoot as ShadowRoot &\n Pick<Document, 'getSelection'>;\n // Firefox and Safari don't implement getSelection for Shadow DOM\n const newSelection = shadowDocument.getSelection\n ? shadowDocument.getSelection()\n : document.getSelection();\n\n if (newSelection && isValidSelection(newSelection)) {\n setSelection(newSelection);\n } else {\n setSelection(null);\n }\n }, waitMillis),\n [shadowRoot, setSelection, waitMillis],\n );\n\n useEffect(() => {\n window.document.addEventListener('selectionchange', handleSelectionChange);\n return () => {\n handleSelectionChange.cancel();\n window.document.removeEventListener(\n 'selectionchange',\n handleSelectionChange,\n );\n };\n }, [handleSelectionChange]);\n\n return selection;\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 { alpha, makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport { ReactNode, PropsWithChildren } from 'react';\nimport { Link } from '../../components/Link';\n\n/** @public */\nexport type HeaderLabelClassKey = 'root' | 'label' | 'value';\n\nconst useStyles = makeStyles(\n theme => ({\n root: {\n textAlign: 'left',\n },\n label: {\n color: theme.page.fontColor,\n fontWeight: theme.typography.fontWeightBold,\n letterSpacing: 0,\n fontSize: theme.typography.fontSize,\n marginBottom: theme.spacing(1) / 2,\n lineHeight: 1,\n },\n value: {\n color: alpha(theme.page.fontColor, 0.8),\n fontSize: theme.typography.fontSize,\n lineHeight: 1,\n },\n }),\n { name: 'BackstageHeaderLabel' },\n);\n\ntype HeaderLabelContentProps = PropsWithChildren<{\n value: ReactNode;\n className: string;\n typographyRootComponent?: keyof JSX.IntrinsicElements;\n}>;\n\nconst HeaderLabelContent = ({\n value,\n className,\n typographyRootComponent,\n}: HeaderLabelContentProps) => {\n return (\n <Typography\n component={\n typographyRootComponent ?? (typeof value === 'string' ? 'p' : 'span')\n }\n className={className}\n >\n {value}\n </Typography>\n );\n};\n\ntype HeaderLabelProps = {\n label: string;\n value?: HeaderLabelContentProps['value'];\n contentTypograpyRootComponent?: HeaderLabelContentProps['typographyRootComponent'];\n url?: string;\n};\n\n/**\n * Additional label to main {@link Header}\n *\n * @public\n *\n */\nexport function HeaderLabel(props: HeaderLabelProps) {\n const { label, value, url, contentTypograpyRootComponent } = props;\n const classes = useStyles();\n const content = (\n <HeaderLabelContent\n className={classes.value}\n value={value || '<Unknown>'}\n typographyRootComponent={contentTypograpyRootComponent}\n />\n );\n return (\n <Grid item>\n <Typography component=\"span\" className={classes.root}>\n <Typography className={classes.label}>{label}</Typography>\n {url ? <Link to={url}>{content}</Link> : content}\n </Typography>\n </Grid>\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 */\n\nimport { PropsWithChildren, useEffect } from 'react';\nimport Helmet from 'react-helmet';\n\nimport Grid from '@material-ui/core/Grid';\nimport Skeleton from '@material-ui/lab/Skeleton';\nimport CodeIcon from '@material-ui/icons/Code';\n\nimport {\n TechDocsAddonLocations as locations,\n useTechDocsAddons,\n useTechDocsReaderPage,\n TechDocsEntityMetadata,\n TechDocsMetadata,\n} from '@backstage/plugin-techdocs-react';\nimport {\n entityPresentationApiRef,\n EntityRefLink,\n EntityRefLinks,\n getEntityRelations,\n} from '@backstage/plugin-catalog-react';\nimport {\n RELATION_OWNED_BY,\n CompoundEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { Header, HeaderLabel } from '@backstage/core-components';\nimport { useRouteRef, configApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport capitalize from 'lodash/capitalize';\n\nimport { rootRouteRef } from '../../../routes';\nimport { useParams } from 'react-router-dom';\n\nconst skeleton = <Skeleton animation=\"wave\" variant=\"text\" height={40} />;\n\n/**\n * Props for {@link TechDocsReaderPageHeader}\n *\n * @public\n * @deprecated No need to pass down properties anymore. The component consumes data from `TechDocsReaderPageContext` instead. Use the {@link @backstage/plugin-techdocs-react#useTechDocsReaderPage} hook for custom header.\n */\nexport type TechDocsReaderPageHeaderProps = PropsWithChildren<{\n entityRef?: CompoundEntityRef;\n entityMetadata?: TechDocsEntityMetadata;\n techDocsMetadata?: TechDocsMetadata;\n}>;\n\n/**\n * Renders the reader page header.\n * This component does not accept props, please use\n * the Tech Docs add-ons to customize it\n * @public\n */\nexport const TechDocsReaderPageHeader = (\n props: TechDocsReaderPageHeaderProps,\n) => {\n const { children } = props;\n const addons = useTechDocsAddons();\n const configApi = useApi(configApiRef);\n\n const entityPresentationApi = useApi(entityPresentationApiRef);\n const { '*': path = '' } = useParams();\n\n const {\n title,\n setTitle,\n subtitle,\n setSubtitle,\n entityRef,\n metadata: { value: metadata, loading: metadataLoading },\n entityMetadata: { value: entityMetadata, loading: entityMetadataLoading },\n } = useTechDocsReaderPage();\n\n useEffect(() => {\n if (!metadata) return;\n setTitle(metadata.site_name);\n setSubtitle(() => {\n let { site_description } = metadata;\n if (!site_description || site_description === 'None') {\n site_description = '';\n }\n return site_description;\n });\n }, [metadata, setTitle, setSubtitle]);\n\n const appTitle = configApi.getOptional('app.title') || 'Backstage';\n\n const { locationMetadata, spec } = entityMetadata || {};\n const lifecycle = spec?.lifecycle;\n\n const ownedByRelations = entityMetadata\n ? getEntityRelations(entityMetadata, RELATION_OWNED_BY)\n : [];\n\n const docsRootLink = useRouteRef(rootRouteRef)();\n\n const labels = (\n <>\n <HeaderLabel\n label={capitalize(entityMetadata?.kind || 'entity')}\n value={\n <EntityRefLink\n color=\"inherit\"\n entityRef={entityRef}\n title={entityMetadata?.metadata.title}\n defaultKind=\"Component\"\n />\n }\n />\n {ownedByRelations.length > 0 && (\n <HeaderLabel\n label=\"Owner\"\n value={\n <EntityRefLinks\n color=\"inherit\"\n entityRefs={ownedByRelations}\n defaultKind=\"group\"\n />\n }\n />\n )}\n {lifecycle ? (\n <HeaderLabel label=\"Lifecycle\" value={String(lifecycle)} />\n ) : null}\n {locationMetadata &&\n locationMetadata.type !== 'dir' &&\n locationMetadata.type !== 'file' ? (\n <HeaderLabel\n label=\"\"\n value={\n <Grid container direction=\"column\" alignItems=\"center\">\n <Grid style={{ padding: 0 }} item>\n <CodeIcon style={{ marginTop: '-25px' }} />\n </Grid>\n <Grid style={{ padding: 0 }} item>\n Source\n </Grid>\n </Grid>\n }\n url={locationMetadata.target}\n />\n ) : null}\n </>\n );\n\n // If there is no entity or techdocs metadata, there's no reason to show the\n // header (hides the header on 404 error pages).\n const noEntMetadata = !entityMetadataLoading && entityMetadata === undefined;\n const noTdMetadata = !metadataLoading && metadata === undefined;\n if (noEntMetadata || noTdMetadata) return null;\n\n const stringEntityRef = stringifyEntityRef(entityRef);\n\n const entityDisplayName =\n entityPresentationApi.forEntity(stringEntityRef).snapshot.primaryTitle;\n\n const removeTrailingSlash = (str: string) => str.replace(/\\/$/, '');\n const normalizeAndSpace = (str: string) =>\n str.replace(/-/g, ' ').split(' ').map(capitalize).join(' ');\n\n let techdocsTabTitleItems: string[] = [];\n\n if (path !== '')\n techdocsTabTitleItems = removeTrailingSlash(path)\n .split('/')\n .slice(0, 3)\n .map(normalizeAndSpace);\n\n const tabTitleItems = [appTitle, entityDisplayName, ...techdocsTabTitleItems];\n const tabTitle = tabTitleItems.join(' | ');\n\n return (\n <Header\n type=\"Documentation\"\n typeLink={docsRootLink}\n title={title || skeleton}\n subtitle={subtitle === '' ? undefined : subtitle || skeleton}\n >\n <Helmet titleTemplate=\"%s\">\n <title>{tabTitle}</title>\n </Helmet>\n {labels}\n {children}\n {addons.renderComponentsByLocation(locations.Header)}\n </Header>\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 { createRouteRef } from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({\n id: 'techdocs:index-page',\n});\n\nexport const rootDocsRouteRef = createRouteRef({\n id: 'techdocs:reader-page',\n params: ['namespace', 'kind', 'name'],\n});\n\nexport const rootCatalogDocsRouteRef = createRouteRef({\n id: 'techdocs:catalog-reader-view',\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 { PropsWithChildren, ReactNode } from 'react';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport { Link } from '@backstage/core-components';\nimport { ResultHighlight } from '@backstage/plugin-search-common';\nimport { HighlightedSearchResultText } from '@backstage/plugin-search-react';\n\nconst useStyles = makeStyles({\n flexContainer: {\n flexWrap: 'wrap',\n },\n itemText: {\n width: '100%',\n marginBottom: '1rem',\n },\n});\n\n/**\n * Props for {@link TechDocsSearchResultListItem}.\n *\n * @public\n */\nexport type TechDocsSearchResultListItemProps = {\n icon?: ReactNode | ((result: any) => ReactNode);\n result?: any;\n highlight?: ResultHighlight;\n rank?: number;\n lineClamp?: number;\n asListItem?: boolean;\n asLink?: boolean;\n title?: string;\n};\n\n/**\n * Component which renders documentation and related metadata.\n *\n * @public\n */\nexport const TechDocsSearchResultListItem = (\n props: TechDocsSearchResultListItemProps,\n) => {\n const {\n result,\n highlight,\n lineClamp = 5,\n asListItem = true,\n asLink = true,\n title,\n icon,\n } = props;\n const classes = useStyles();\n\n const LinkWrapper = ({ children }: PropsWithChildren<{}>) =>\n asLink ? (\n <Link noTrack to={result.location}>\n {children}\n </Link>\n ) : (\n <>{children}</>\n );\n\n const TextItem = () => {\n const resultTitle = highlight?.fields.title ? (\n <HighlightedSearchResultText\n text={highlight.fields.title}\n preTag={highlight.preTag}\n postTag={highlight.postTag}\n />\n ) : (\n result.title\n );\n\n const entityTitle = highlight?.fields.entityTitle ? (\n <HighlightedSearchResultText\n text={highlight.fields.entityTitle}\n preTag={highlight.preTag}\n postTag={highlight.postTag}\n />\n ) : (\n result.entityTitle\n );\n\n const resultName = highlight?.fields.name ? (\n <HighlightedSearchResultText\n text={highlight.fields.name}\n preTag={highlight.preTag}\n postTag={highlight.postTag}\n />\n ) : (\n result.name\n );\n\n if (!result) return null;\n\n return (\n <ListItemText\n className={classes.itemText}\n primaryTypographyProps={{ variant: 'h6' }}\n primary={\n <LinkWrapper>\n {title ? (\n title\n ) : (\n <>\n {resultTitle} | {entityTitle ?? resultName} docs\n </>\n )}\n </LinkWrapper>\n }\n secondary={\n <Typography\n component=\"span\"\n style={{\n display: '-webkit-box',\n WebkitBoxOrient: 'vertical',\n WebkitLineClamp: lineClamp,\n overflow: 'hidden',\n }}\n color=\"textSecondary\"\n variant=\"body2\"\n >\n {highlight?.fields.text ? (\n <HighlightedSearchResultText\n text={highlight.fields.text}\n preTag={highlight.preTag}\n postTag={highlight.postTag}\n />\n ) : (\n result.text\n )}\n </Typography>\n }\n />\n );\n };\n\n const ListItemWrapper = ({ children }: PropsWithChildren<{}>) =>\n asListItem ? (\n <>\n {icon && (\n <ListItemIcon>\n {typeof icon === 'function' ? icon(result) : icon}\n </ListItemIcon>\n )}\n <div className={classes.flexContainer}>{children}</div>\n </>\n ) : (\n <>{children}</>\n );\n\n return (\n <ListItemWrapper>\n <TextItem />\n </ListItemWrapper>\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\n// This script is used to pick up and set the public path of the Webpack bundle\n// at runtime. The meta tag is injected by the app build, but only present in\n// the `index.html.tmpl` file. The runtime value of the meta tag is populated by\n// the app backend, when it templates the final `index.html` file.\n//\n// This is needed for additional chunks to use the correct public path, and it\n// is not possible to set the `__webpack_public_path__` variable outside of the\n// build itself. The Webpack output also does not read any <base> tags or\n// similar, this seems to be the only way to dynamically configure the public\n// path at runtime.\nconst el = document.querySelector('meta[name=\"backstage-public-path\"]');\nconst path = el?.getAttribute('content');\nif (path) {\n __webpack_public_path__ = path;\n}\n"],"names":["CATALOG_FILTER_EXISTS","Symbol","DEFAULT_NAMESPACE","ANNOTATION_VIEW_URL","ANNOTATION_EDIT_URL","getCompoundEntityRef","entity","parseEntityRef","ref","context","kind","namespace","name","Error","defaultKind","defaultNamespace","parsed","parseRefString","colonI","slashI","undefined","Math","TypeError","textual","JSON","stringifyEntityRef","RELATION_OWNED_BY","RELATION_DEPENDS_ON","RELATION_DEPENDENCY_OF","RELATION_PART_OF","RELATION_HAS_PART","ANNOTATION_LOCATION","ANNOTATION_SOURCE_LOCATION","scriptProtocolPattern","parseLocationRef","splitIndex","type","target","stringifyLocationRef","getEntitySourceLocation","locationRef","CodeSnippet","props","text","language","showLineNumbers","highlightedNumbers","customStyle","showCopyCodeButton","theme","useTheme","mode","dark","docco","highlightColor","Box","LightAsync","lineNumber","CopyTextButton","t","useTranslationRef","coreComponentsTranslationRef","tooltipDelay","tooltipText","ariaLabel","errorApi","useApi","errorApiRef","open","setOpen","useState","error","copyToClipboard","useCopyToClipboard","useEffect","Tooltip","IconButton","e","CopyIcon","useStyles","makeStyles","EmptyStateImage","missing","classes","missingAnnotation","noInformation","createComponent","noBuild","EmptyState","title","description","action","Grid","Typography","ErrorList","message","stack","children","List","ListItem","ListItemText","ErrorPanel","defaultExpanded","titleFormat","WarningPanel","FavoriteToggleIcon","isFavorite","StarIcon","UnstarredIcon","ExternalLinkIcon","Icon","app","useApp","OpenInNew","isExternalUri","uri","originalWindowOpen","window","newOpen","args","url","String","getNodeText","node","Array","Link","forwardRef","onClick","noTrack","externalLinkIcon","analytics","useAnalytics","to","isReactRouterBeta","obj","createRoutesFromChildren","Route","useResolvedPath","resolvedPath","basePath","useBasePath","pathname","URL","useBaseUrl","config","configApiRef","trimEnd","external","startsWithBasePath","linkText","newWindow","handleClick","event","MaterialLink","classnames","RouterLink","LinkWrapper","LinkButton","MaterialButton","flatten","child","Children","headingRenderer","level","slug","childrenArray","createElement","components","inline","className","match","MarkdownContent","content","dialect","linkTarget","transformLinkUri","transformImageUri","ReactMarkdown","gfm","Progress","isVisible","setIsVisible","handle","setTimeout","clearTimeout","LinearProgress","createStyles","SvgIcon","BootstrapInput","withStyles","InputBase","SelectComponent","multiple","items","label","placeholder","selected","onChange","triggerReset","native","disabled","margin","dataTestId","value","setValue","isOpen","FormControl","InputLabel","Select","previous","HTMLElement","s","selectedValue","item","el","Chip","CancelIcon","newValue","chip","OpenedDropdown","ClosedDropdown","MenuItem","Checkbox","SupportIcon","icon","HelpIcon","SupportLink","link","SupportListItem","ListItemIcon","prev","idx","SupportButton","configItems","useSupportConfig","popoverOpen","setPopoverOpen","anchorEl","setAnchorEl","supportConfig","isSmallScreen","useMediaQuery","onClickHandler","popoverCloseHandler","Button","Popover","MenuList","Boolean","i","DialogActions","useFilterStyles","Filters","onChangeFilters","selectedFilters","setSelectedFilters","reset","filter","TableLoadingBody","CircularProgress","tableIcons","AddBox","Check","Clear","DeleteOutline","ChevronRight","Edit","SaveAlt","FilterList","FirstPage","LastPage","ChevronLeft","Search","ArrowUpward","Remove","ViewColumn","extractValueByField","data","field","path","StyledMTableHeader","MTableHeader","StyledMTableToolbar","MTableToolbar","useTableStyles","defaultInitialState","TableToolbar","toolbarProps","toolbarRef","setSearch","hasFilters","selectedFiltersLength","toggleFilters","filtersClasses","onSearchChanged","useCallback","searchText","Table","filterConfig","dataValue","columns","emptyContent","options","subtitle","localization","filters","initialState","onStateChange","loading","style","restProps","tableClasses","calculatedInitialState","filtersOpen","setFiltersOpen","v","search","state","transform","result","key","isEqual","defaultState","getFieldByTitle","titleValue","tableData","useMemo","selectedFiltersArray","Object","filterValue","fieldValue","Toolbar","hasNoRows","columnCount","Body","makeBody","bodyProps","MTableBody","extractDistinctValues","distinctValues","Set","addValue","c","MTable","column","headerStyle","cellStyle","cellStyleFn","rowData","rowColumn","getWarningTextColor","severity","getColor","darken","lighten","getWarningBackgroundColor","getBackgroundColor","useErrorOutlineStyles","ErrorOutlineStyled","ErrorOutline","ExpandMoreIconStyled","ExpandMoreIcon","subTitle","capitalize","Accordion","AccordionSummary","AccordionDetails","apiHolder","useApiHolder","defaultSupportConfig","useDefaultSupportConfig","itemConf","linkConf","AppIcon","Fallback","MuiBrokenImageIcon","rest","Content","stretch","noPadding","classNames","ContentHeaderTitle","ContentHeaderDescription","ContentHeader","TitleComponent","DescriptionComponent","textAlign","renderedTitle","renderedDescription","Helmet","MicDrop","MicDropSvgUrl","StackDetails","detailsOpen","setDetailsOpen","ErrorPage","status","statusMessage","additionalInfo","supportUrl","navigate","useNavigate","support","ClickableText","StyledBox","BreadcrumbsCurrentPage","Breadcrumbs","firstPage","secondPage","expandablePages","currentPage","hasHiddenBreadcrumbs","Fragment","MaterialBreadcrumbs","pageLink","index","TypeFragment","typeLink","pageTitle","TitleFragment","tooltip","contentRef","useContent","FinalTitle","SubtitleFragment","Header","pageTitleOverride","appTitle","configApi","documentTitle","titleTemplate","defaultTitle","Page","themeId","ThemeProvider","baseTheme","PageWithHeader","LocalStorage","PageContext","createContext","SidebarPage","isPinned","setIsPinned","sidebarConfig","useContext","SidebarConfigContext","useRef","pageContext","isMobile","SidebarPinStateProvider","toggleSidebarPinState","focusContent","defaultSidebarPinStateContext","LegacySidebarPinStateContext","VersionedSidebarPinStateContext","createVersionedContext","createVersionedValueMap","useSidebarPinState","versionedPinStateContext","legacyPinStateContext","pinStateContext","drawerWidthClosed","iconPadding","userBadgePadding","makeSidebarConfig","customSidebarConfig","submenuConfig","makeSidebarSubmenuConfig","customSubmenuConfig","SidebarItemWithSubmenuContext","createTranslationRef","AnalyticsReactContext","useAnalyticsContext","theContext","theValue","AnalyticsContext","attributes","combinedValue","versionedCombinedValue","globalEvents","getOrCreateGlobalSingleton","routableExtensionRenderedEvent","Tracker","analyticsApi","addEventListener","subject","_routeNodeType","console","trackerRef","useAnalyticsApi","analyticsApiRef","tracker","alertApiRef","createApiRef","discoveryApiRef","FeatureFlagState","featureFlagsApiRef","fetchApiRef","identityApiRef","translationApiRef","ApiRefImpl","part","createApiFactory","factory","instance","versionedHolder","useVersionedContext","NotImplementedError","apiRef","api","versionedContext","appContext","globalStore","WeakMap","componentDataKey","attachComponentData","component","container","dataComponent","Map","getComponentData","PluginErrorBoundary","Component","plugin","ErrorBoundaryFallback","createRoutableExtension","mountPoint","createReactExtension","InnerComponent","RoutableExtensionWrapper","useRouteRef","componentName","createComponentExtension","lazyLoader","lazy","ofExtension","ForwardedError","Result","Suspense","selectChildren","rootNode","featureFlagsApi","selector","strictError","isValidElement","Collection","query","selection","useElementFilter","filterFn","dependencies","elements","PluginImpl","extension","createPlugin","RouteRefImpl","routeRefType","id","params","createRouteRef","routeRef","useLocation","resolver","routeFunc","isOptional","TranslationRefImpl","flattenMessages","nested","entries","visit","prefix","resources","createTranslationResource","toInternalTranslationRef","r","toInternalTranslationResource","resource","loader","m","loggedRefs","WeakSet","translationRef","translationApi","snapshot","setSnapshot","observable","onError","errMsg","subscription","next","initialRenderRef","Promise","resolve","parseErrorResponseBody","response","body","ResponseError","statusCode","statusText","cause","deserializeError","opts","isError","maybe","CustomErrorBase","fullMessage","causeStr","stringifyError","baseName","NotFoundError","deserializeErrorInternal","str","AMAZON_AWS_HOST","readAwsS3IntegrationConfig","host","endpoint","s3ForcePathStyle","accessKeyId","secretAccessKey","roleArn","externalId","AwsS3Integration","configs","readAwsS3IntegrationConfigs","basicIntegrations","integrationConfig","defaultScmResolveUrl","readAwsCodeCommitIntegrationConfig","region","AwsCodeCommitIntegration","repositoryName","pathMatch","parsedUrl","RegExp","AzureUrl","repoUrl","owner","project","repo","parts","decodeURIComponent","version","origin","encodeURIComponent","VERSION_PREFIX_GIT_BRANCH","AZURE_HOST","AzureDevOpsCredentialFields","AzureDevopsCredentialFieldMap","asAzureDevOpsCredential","credential","entry","requiredFields","forbiddenFields","acc","readAzureIntegrationConfig","credentials","credentialConfigs","token","mapped","isValidHost","errors","credentialConfig","organization","_","indexes","org","AzureIntegration","readAzureIntegrationConfigs","base","isValidUrl","azureUrl","newUrl","mockBaseUrl","updatedPath","BITBUCKET_CLOUD_HOST","BITBUCKET_CLOUD_API_BASE_URL","readBitbucketCloudIntegrationConfig","apiBaseUrl","username","appPassword","BitbucketCloudIntegration","readBitbucketCloudIntegrationConfigs","resolved","urlData","parseGitUrl","editUrl","BITBUCKET_HOST","BITBUCKET_API_BASE_URL","readBitbucketIntegrationConfig","BitbucketIntegration","readBitbucketIntegrationConfigs","readBitbucketServerIntegrationConfig","password","BitbucketServerIntegration","readGerritIntegrationConfig","baseUrl","cloneUrl","disableEditUrl","gitilesBaseUrl","parseGitilesUrlRef","baseUrlParse","urlParse","urlPath","trimStart","p","projectParts","takeWhile","join","remainingPath","refsRegexp","refType","matchString","refsReference","GerritIntegration","updated","branch","filePath","GITLAB_HOST","GITLAB_API_BASE_URL","readGitLabIntegrationConfig","GitLabIntegration","readGitLabIntegrationConfigs","GiteaIntegration","giteaConfigs","readGiteaConfig","gitea","giteaUrl","parseGiteaUrl","_blank","_src","_branch","pathWithoutSlash","HarnessIntegration","harnessConfigs","readHarnessConfig","apiKey","harness","parseHarnessUrl","pathUrl","pathSegments","segment","urlParts","accountIdIndex","accountId","orgNameIndex","orgName","projectNameIndex","projectName","repoNameIndex","repoName","refAndPath","refIndex","refString","readAzureBlobStorageIntegrationConfig","accountName","accountKey","sasToken","connectionString","endpointSuffix","aadCredential","AzureBlobStorageIntergation","readAzureBlobStorageIntegrationConfigs","ScmIntegrations","GithubIntegration","integrationsByType","candidates","filteredCandidates","x","integration","ScmIntegrationsApi","scmIntegrationsApiRef","GITHUB_HOST","GITHUB_API_BASE_URL","GITHUB_RAW_BASE_URL","readGithubIntegrationConfig","rawBaseUrl","apps","readGithubIntegrationConfigs","replaceGithubUrlType","check","integrations","getHost","href","filepath","repoRootPath","SessionState","ScopePriority","OptionallyWrapInRouter","useInRouterContext","MemoryRouter","BrowserRouter","step","resetError","ERROR_PREFIX","UrlPatternDiscovery","pattern","urlStr","pluginId","FrontendHostDiscovery","discovery","endpoints","defaultEndpoint","PublishSubject","ObservableImpl","subscriber","onNext","onComplete","BehaviorSubject","AlertApiForwarder","alert","NoOpAnalyticsApi","_event","ErrorAlerter","alertApi","ErrorApiForwarder","UnhandledErrorForwarder","errorContext","buckets","WebStorage","bucketPath","webStorage","presence","localStorage","_key","val","messageKey","eventKey","trimmedKey","IdentityAuthInjectorFetchMiddleware","matcher","buildPrefixMatcher","headerName","headerValue","endpointConfigs","plugins","identityApi","allowUrl","input","init","request","Request","prefixes","trimmedPrefixes","PluginProtocolResolverFetchMiddleware","discoveryApi","left","a","hostname","hash","authority","right","FetchMiddlewares","OAuthPendingRequests","scopes","reject","hasScopes","searched","searchFor","scope","currentScopes","current","joinScopes","moreScopess","moreScopes","reason","OAuthRequestManager","handler","scopeRequest","newRequests","warned","defaultJoinScopes","DefaultAuthConnector","environment","provider","oauthRequestApi","sessionTransform","popupOptions","res","fetch","authInfo","popupUrl","width","height","payload","top","popup","targetOrigin","messageListener","authResult","done","intervalId","setInterval","clearInterval","queryString","SessionScopeHelper","session","newScope","googleAuthApiRef","githubAuthApiRef","oktaAuthApiRef","gitlabAuthApiRef","microsoftAuthApiRef","oneloginAuthApiRef","bitbucketAuthApiRef","bitbucketServerAuthApiRef","atlassianAuthApiRef","vmwareCloudAuthApiRef","SessionStateTracker","isSignedIn","RefreshingAuthSessionManager","connector","defaultScopes","sessionScopes","sessionShouldRefresh","alreadyTriedToRefreshSession","refreshedSession","refreshedScopes","newSession","DEFAULT_PROVIDER","OAuth2","scopeTransform","backstageIdentity","Date","sessionManager","min","Infinity","normalizedScopes","scopeList","SCOPE_PREFIX","GoogleAuth","MicrosoftAuth","audiences","aud","groups","resourceURI","GithubAuth","OKTA_OIDC_SCOPES","OKTA_SCOPE_PREFIX","OktaAuth","GitlabAuth","OIDC_SCOPES","OneLoginAuth","BitbucketAuth","BitbucketServerAuth","AtlassianAuth","VMwareCloudAuth","storageApiRef","oauthRequestApiRef","permissionCriteriaSchema","z","authorizePermissionResponseSchema","AuthorizeResult","authorizePermissionResponseBatchSchema","queryPermissionResponseSchema","PermissionClient","requests","queries","itemSchema","uuid","responsesById","parsedResponse","permission","resourceRef","isResourcePermission","ids","permissionApi","responseBody","responseSchema","IdentityPermissionApi","permissionClient","identity","apis","createFetchApi","global","permissionApiRef","icons","MuiMenuBookIcon","MuiCreateNewFolderIcon","MuiSubjectIcon","MuiSearchIcon","MuiChatIcon","MuiDashboardIcon","MuiDocsIcon","MuiEmailIcon","MuiGitHubIcon","MuiPeopleIcon","MuiHelpIcon","MuiExtensionIcon","MuiMemoryIcon","MuiApartmentIcon","MuiLocationOnIcon","MuiCategoryIcon","MuiPersonIcon","MuiStorageIcon","MuiFeaturedPlayListIcon","MuiWarningIcon","Star","StarBorder","ClassNameGenerator","generateV4ClassName","createGenerateClassName","UnifiedThemeProvider","cssBaseline","noCssBaseline","v4Theme","v5Theme","themeMode","themeName","document","CssBaseline","StylesProvider","StyledEngineProvider","Mui5Provider","genPageTheme","colors","shape","gradientColors","gradient","backgroundImage","pageTheme","DEFAULT_FONT_FAMILY","defaultTypography","defaultComponentThemes","stateStyleKeyPattern","UnifiedThemeHolder","v4","v5","createUnifiedTheme","themeOptions","createBaseThemeOptions","palette","htmlFontSize","fontFamily","defaultPageTheme","defaultPageThemes","typography","createV5Theme","v4Overrides","transformV5ComponentThemesToV4","overrides","adaptV5CssBaselineOverride","styles","extractV5StateOverrides","output","_styleKey","styleKey","stateStyles","restStyles","adaptV5Override","_theme","defaultSpacing","argsInput","argument","themeSpacing","createTheme","themes","LightIcon","builtinThemes","DarkIcon","ApiAggregator","holders","holder","ApiContext","ApiProvider","parentHolder","PropTypes","CONFIG_KEY_PART_PATTERN","isObject","merge","into","from","fromObj","out","typeOf","isNaN","typeName","expected","ConfigReader","previousReader","filteredKeys","deprecatedKeys","reader","fallback","k","cloneDeep","fallbackValue","fallbackConfig","values","number","Number","valueString","validate","keyName","STORAGE_KEY","AppThemeSelector","initialThemeId","validateFlagName","LocalStorageFeatureFlags","flag","enabled","jsonStr","json","appThemeApiRef","appLanguageApiRef","ApiFactoryRegistry","priority","existing","tuple","refs","ApiResolver","factories","heap","allDeps","dep","impl","deps","dependent","impls","createCollector","accumulatorFactory","childDiscoverer","element","routeElementDiscoverer","pluginCollector","FeatureFlagged","featureFlagApi","isEnabled","MATCH_ALL_ROUTE","stringifyNode","anyNode","pluginSet","set","routingV2Collector","parent","ctx","pathProp","parentChildren","elementProp","newObj","others","collectSubTree","mountPointPlugin","routingV1Collector","currentObj","currentParentRouteRef","sticky","caseSensitive","currentCtxPath","routePath","featureFlagCollector","isRouteRef","isSubRouteRef","joinPaths","paths","normalized","RouteResolver","routePaths","routeParents","routeObjects","routeBindings","appBasePath","anyRouteRef","sourceLocation","relativeSourceLocation","targetRef","targetPath","resolveTargetRef","subRoutePath","resolvedRoute","resolveBasePath","matchRoutes","refDiffList","matchIndex","targetSearchRef","parentPath","diffPaths","encodedParams","mapValues","generatePath","RoutingContext","RoutingProvider","versionedValue","AppContext","AppContextProvider","mkError","thing","logDeprecation","AppIdentityProxy","targetOptions","stopRefresh","startCookieAuthRefresh","fetchApi","timeout","stopped","firstError","errorBackoff","channel","BroadcastChannel","getDelay","expiresAt","refresh","requestUrl","scheduleRefresh","onMessage","delayMs","appBaseUrl","AppThemeProvider","appThemeApi","appTheme","resolveTheme","shouldPreferDark","selectedTheme","darkTheme","lightTheme","useObservable","useShouldPreferDarkTheme","mediaQuery","setPrefersDark","listener","defaultConfigLoader","defaultConfigLoaderSync","runtimeConfigJson","staticConfig","process","configScripts","windowAppConfig","ApiRegistryBuilder","ApiRegistry","InternalAppContext","TrackNavigation","RouteTracker","getExtensionContext","routes","matches","routeMatch","routeObject","readBasePath","SignInPageWrapper","appIdentityProxy","setIdentityApi","AppRouter","RouterComponent","SignInPageComponent","mountPath","internalAppContext","Routes","AppLanguageSelector","languages","initialLanguage","storedLanguage","lng","removeNulls","messages","ResourceLoader","onLoad","internalResource","load","JsxInterpolator","i18n","formatHook","interpolator","originalFormat","format","formatOpts","hook","marker","setFormatHook","originalT","elementsMap","elementKey","split","I18nextTranslationApi","createI18n","loaded","jsxInterpolator","internalRef","loadTicket","loadResource","ticket","unwrappedT","defaultMessages","defaultResource","createLocalBaseUrl","fullUrl","AppContextImpl","AppManager","AppProvider","routeValidationError","needsFeatureFlagRegistrationRef","routing","featureFlags","usesReactRouterBeta","traverseElementTree","collectors","queue","contexts","nextContexts","collector","discoverer","loadedConfig","useConfigLoader","configLoader","noConfigNode","hasConfig","useAsync","BootErrorPage","overrideBaseUrlConfigs","inputConfigs","newBackendBaseUrl","newAppBaseUrl","urlConfigReader","backendBaseUrl","appOrigin","maybeNewBackendBaseUrl","maybeNewAppBaseUrl","hasConfigApi","resolveRouteBindings","bindRoutes","routesById","collectRouteIds","externalRoutesById","refId","disabledExternalRefs","bind","externalRoutes","targetRoutes","externalRoute","bindings","externalRefId","targetRefId","externalRef","defaultRefId","defaultRef","validateRouteParameters","notLeafRoutes","route","currentRouteRef","fullPath","j","externalRouteRef","flagNames","registeredFlags","f","isProtectedApp","appMode","languageApi","pluginIds","FlatRoutes","NotFoundErrorPage","isBeta","withNotFound","b","useRoutes","DefaultApiClient","crossFetch","parser","CatalogClient","entityRef","fields","order","offset","limit","after","encodedOrder","directive","getOneChunk","splitRefsIntoChunks","maxCountPerChunk","maxStringLengthPerChunk","extraStringLengthPerRef","chunks","currentChunkStart","currentChunkStringLength","currentChunkSize","refLength","entities","cursor","orderFields","fullTextFilter","normalizedFullTextFilterTerm","compoundName","facets","dryRun","location","exists","all","l","uid","filterItem","filterParts","performMigrationToTheNewBucket","storageApi","source","oldStarredEntities","isArray","targetEntities","isString","old","DefaultStarredEntitiesApi","durationToMilliseconds","duration","years","months","weeks","days","hours","minutes","seconds","milliseconds","totalSeconds","totalMinutes","totalHours","totalDays","DEFAULT_CACHE_TTL","DEFAULT_BATCH_DELAY","DEFAULT_ICONS","ExtensionIcon","MemoryIcon","CategoryIcon","StorageIcon","ApartmentIcon","LocationOnIcon","PersonIcon","PeopleIcon","FeaturedPlayListIcon","createDefaultRenderer","defaultEntityPresentation","ExpiryMap","ttlMs","timestamp","DefaultEntityPresentationApi","cacheTtl","batchDelay","renderer","kindIcons","entityOrRef","initialSnapshot","needsLoad","render","maybeUpdatedSnapshot","newEntity","aborted","updatedSnapshot","promise","cached","cachedEntity","cacheNeedsUpdate","cacheTtlMs","batchDelayMs","DataLoader","entityRefs","now","cb","renderedIcon","catalogPlugin","catalogApiRef","starredEntitiesApiRef","entityPresentationApiRef","catalogApi","rootRouteRef","entityRouteRef","createComponentRouteRef","viewTechDocRouteRef","createFromTemplateRouteRef","unregisterRedirectRouteRef","CatalogEntityPage","createSearchResultListItemExtension","TechDocsDevStorageApi","_entityId","apiOrigin","oldBaseUrl","TechDocsDevApi","tenMinutesFromNow","techdocsStorageApiRef","techdocsApiRef","PRODUCTION_CONFIG","DEVELOPMENT_CONFIG","isProductionServe","isProduction","defaultSidebarOpenStateContext","LegacySidebarContext","VersionedSidebarContext","SidebarOpenStateProvider","useSidebarOpenState","versionedOpenStateContext","legacyOpenStateContext","openStateContext","MobileSidebarContext","MobileSidebarGroup","selectedMenuItemIndex","setSelectedMenuItemIndex","BottomNavigationAction","SidebarGroup","sidebarGroupType","OverlayMenu","onClose","Drawer","CloseIcon","MobileSidebar","sidebarGroups","orderBy","MenuIcon","shouldShowGroupChildren","BottomNavigation","DesktopSidebar","openDelayMs","closeDelayMs","disableExpandOnHover","setState","hoverTimerRef","handleOpen","handleClose","A11ySkipSidebar","Sidebar","isLocationMatch","currentLocation","toLocation","exact","toDecodedSearch","URLSearchParams","toQueryParameters","qs","currentDecodedSearch","currentQueryParameters","queryStringMatcher","isMatch","useMemoStyles","isButtonItem","sidebarSubmenuType","isHoveredOn","isSubmenuOpen","setIsSubmenuOpen","WorkaroundNavLink","end","activeStyle","activeClassName","ariaCurrentProp","locationPathname","toPathname","isActive","ariaCurrent","SidebarItemBase","hasNotifications","hasSubmenu","disableHighlight","navLinkProps","displayItemIcon","ArrowRightIcon","itemIcon","Badge","openContent","childProps","SidebarItemWithSubmenu","setIsHoveredOn","submenu","active","dropdownItems","_to","resolvePath","handleMouseEnter","handleMouseLeave","ArrowDropUp","ArrowDropDown","SidebarItem","styled","SidebarDivider","scrollbarStyles","useSidebarLogoStyles","SidebarLogo","LogoFull","LogoIcon","Root","LibraryBooks","techDocsPage","TechDocsReaderPage","TechDocsReaderPageHeader","TechDocsReaderPageContent","DefaultTechDocsPage","ThemeToggleAddon","techdocsPlugin","createTechDocsAddonExtension","setTheme","prevTheme","newTheme","TechDocsAddonLocations","Navigate","TechDocsIndexPage","DefaultTechDocsHome","TechDocsAddons","ReactDOM","App","versions","globalObject","self","Function","supplier","displayName","getParts","get","primary","getShortRef","defaultKindLower","defaultNamespaceLower","candidate","secondary","useEntityPresentation","entityPresentationApi","presentation","useUpdatingObservable","updatedValue","BootstrapAutocomplete","Autocomplete","PopperComponent","Popper","TransitionProps","Grow","PaperComponent","Paper","CatalogAutocomplete","LabelProps","TextFieldProps","renderInput","TextField","autocomplete","CatalogFilterLayout","isScreenSmallerThanBreakpoint","filterDrawerOpen","setFilterDrawerOpen","catalogReactTranslationRef","FilterListIcon","CheckBoxOutlineBlankIcon","checkedIcon","CheckBoxIcon","OptionCheckbox","EntityAutocompletePickerOption","memo","availableOptions","showCounts","FormControlLabel","EntityAutocompletePicker","Filter","InputProps","initialSelectedOptions","filtersForAvailableValues","hidden","updateFilters","queryParameter","useEntityList","availableValuesFilters","availableValues","reduceBackendCatalogFilters","count","queryParameters","filteredOptions","selectedOptions","setSelectedOptions","shouldAddFilter","newSelectedOptions","option","FixedWidthFormControlLabel","RenderOptionLabel","isGroup","GroupIcon","EntityOwnerPicker","ownersParameter","setText","queryParamOwners","selectedOwners","setSelectedOwners","handleFetch","cache","useFetchEntities","initialSelectedOwnersRefs","isOwnersOnlyMode","queryEntitiesResponse","useQueryEntities","useAsyncFn","cursorRequest","initialRequest","facetsEntitiesResponse","useFacetsEntities","facetsPromise","facet","start","isFacetsResponse","atob","filteredRefs","filterEntity","normalizedText","encodeCursor","btoa","useSelectedOwners","allEntities","initialSelectedEntities","useMountEffect","useDebouncedEffect","availableOwners","EntityOwnerFilter","o","humanizeEntity","humanizeEntityRef","owners","_e","inputValue","hasReachedEnd","EntityDisplayName","hideIcon","disableTooltip","primaryTitle","secondaryTitle","EntityRefLink","linkProps","entityRoute","entityRouteParams","EntityRefLinks","hideIcons","entityRefString","defaultName","EntityTagPicker","EntityTagFilter","UserListPicker","initialFilter","availableFilters","alwaysKeepFilters","kindParameter","userParameter","userAndGroupFilterIds","filterGroups","getFilterGroups","SettingsIcon","filterGroup","ownedEntitiesCount","loadingOwnedEntities","ownedEntitiesFilter","useOwnedEntitiesCount","ownershipEntityRefs","loadingEntityRefs","user","allFilters","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","ListItemSecondaryAction","EntityKindFilter","EntityTypeFilter","EntityTextFilter","words","exactMatch","partialMatch","word","fullRefs","err","getEntityRelations","EntityLifecycleFilter","EntityNamespaceFilter","starredEntityRefs","relations","UserListFilter","isOwnedEntity","isStarredEntity","EntityOrphanFilter","orphan","EntityErrorFilter","EntityListContext","EntityListProvider","isMounted","useMountedState","requestedFilters","setRequestedFilters","paginationMode","paginationLimit","initialCursor","initialOffset","initialLimit","queryLimit","setCursor","setOffset","setLimit","outputState","setOutputState","resolvedValue","kindValue","adjustedFilters","entityFilter","reduceEntityFilters","backendFilter","previousBackendFilter","useDebounce","queryParams","oldParams","newParams","update","prevFilters","newFilters","pageInfo","prevCursor","nextCursor","getEntityRef","starredEntitiesApi","toggleStarredEntity","encodeParams","isEntityTextFilter","isEntityOrderFilter","condensedFilters","compoundFilter","backendCatalogFilters","relationType","entityNames","ExternalRouteRefImpl","optional","defaultTarget","createExternalRouteRef","resourceType","HighlightedSearchResultText","preTag","postTag","terms","SearchResultListItemExtension","rank","alignItems","handleClickCapture","predicate","TECHDOCS_ANNOTATION","TECHDOCS_EXTERNAL_ANNOTATION","TECHDOCS_EXTERNAL_PATH_ANNOTATION","TECHDOCS_ADDONS_KEY","TECHDOCS_ADDONS_WRAPPER_KEY","getDataKeyByName","TechDocsAddon","getAllTechDocsAddons","collection","getAllTechDocsAddonsData","useTechDocsAddons","useOutlet","findAddonByData","nameKey","renderComponentByName","renderComponentsByLocation","defaultTechDocsReaderPageValue","TechDocsReaderPageContext","TechDocsReaderPageProvider","techdocsApi","entityMetadata","useAsyncRetry","setTitle","setSubtitle","shadowRoot","setShadowRoot","toLowercaseEntityRefMaybe","prevProps","nextProps","prevEntityRef","nextEntityRef","useTechDocsReaderPage","getEntityRootTechDocsPath","buildTechDocsURL","techdocsRef","toLowerMaybe","TechDocsFilter","TechDocsPicker","OffsetPaginatedDocsTable","actions","isLoading","page","setPage","newPage","pageSize","CursorPaginatedDocsTable","EntityListDocsTable","getRouteToReaderPageFor","rootDocsRouteRef","defaultActions","actionFactories","documents","entitiesToDocsMapper","defaultColumns","DocsTable","columnFactories","ownerPickerMode","pagination","PageWrapper","CustomHeader","Wrapper","TechDocsPageWrapper","paging","row","ShareIcon","isStarred","useSubvalueCellStyles","SubvalueCell","subvalue","customTitle","row1","row2","title1","title2","ownedByRelations","CustomPageWrapper","generatedSubtitle","TechDocsClient","entityId","TechDocsStorageClient","storageUrl","errorMessage","logHandler","ctrl","AbortController","fetchEventSource","newBaseUrl","rootCatalogDocsRouteRef","ReactDOMPromise","SHADOW_DOM_STYLE_LOAD_EVENT","useShadowDomStylesLoading","setLoading","handleLoad","TechDocsShadowDom","onAppend","jss","setJss","create","jssPreset","CustomEvent","shadowHost","searchApiRef","SearchContext","useSearch","defaultInitialSearchState","LocalSearchContext","useSearchContextValue","initialValue","searchApi","term","setTerm","types","setTypes","setFilters","pageLimit","setPageLimit","pageCursor","setPageCursor","prevTerm","usePrevious","resultSet","hasNextPage","hasPreviousPage","fetchNextPage","fetchPreviousPage","SearchContextProvider","inheritParentContextIfAvailable","hasParentContext","configInitialSearchState","searchContextInitialState","searchReactTranslationRef","SearchBarBase","onKeyDown","onClear","onSubmit","debounceTime","clearButton","fullWidth","defaultValue","inputProps","endAdornment","forwardedValueRef","prevValue","handleChange","handleKeyDown","handleClear","inputPlaceholder","SearchIcon","DefaultSearchIcon","startAdornment","InputAdornment","clearButtonEndAdornment","SearchBar","SearchAutocompleteLoadingAdornment","SearchAutocomplete","getOptionLabel","inputDebounceTime","freeSolo","clearOnBlur","getInputValue","details","InputLabelProps","TechDocsSearchBar","entityTitle","searchResultUrlMapper","searchVal","setOptions","highlight","TechDocsSearchResultListItem","TechDocsSearch","RealLogViewer","LogViewer","useDrawerStyles","TechDocsBuildLogsDrawerContent","buildLog","logText","Close","TechDocsBuildLogs","TechDocsNotFound","techdocsBuilder","reducer","oldState","newState","TechDocsReaderContext","useTechDocsReader","TechDocsReaderProvider","useParams","useReaderState","dispatch","useReducer","techdocsStorageApi","contentReload","entityDocs","buildingTimeout","log","displayState","calculateDisplayState","contentLoading","activeSyncState","TechDocsStateIndicator","StateAlert","contentErrorMessage","syncErrorMessage","Alert","MKDOCS_CSS","GOOGLE_FONTS","GSTATIC_FONTS","removeUnsafeLinks","isLink","isSafe","isMkdocsCss","isGoogleFonts","isGstaticFonts","headings","relativeLengthUnit","cssVariable","themeHashes","rules","alpha","sidebar","heading","lineHeight","fontWeight","fontSize","calculate","factor","html","transformers","dom","DOMParser","Element","transformer","isSvgNeedingInlining","attrName","attrVal","isSrcToSvg","isRelativeUrl","pointsToOurBackend","normalizeUrl","renderReactElement","root","TechDocsRedirectNotification","handleButtonClick","autoHideDuration","Snackbar","CopyToClipboardTooltip","CopyToClipboardIcon","CopyToClipboardButton","onCssReady","onLoading","onLoaded","handleShadowDomStyleLoad","TechDocsReaderPageContentAddons","addons","contentElement","primarySidebarElement","primarySidebarAddonLocation","secondarySidebarElement","secondarySidebarAddonLocation","Portal","locations","withSearch","onReady","entityMetadataLoading","useTechDocsReaderDom","defaultPath","useNavigateUrl","resolveUrlToRelative","parsedAppUrl","appUrlPath","relativeUrl","isMobileMedia","sanitizerTransformer","useSanitizerTransformer","useSanitizerConfig","hosts","DOMPurify","tags","isIframe","src","currNode","tagNameCheck","attributeNameCheck","allowedURIProtocols","allowedURIRegExp","stylesTransformer","useStylesTransformer","useRuleStyles","rule","scmIntegrationsApi","rawPage","currPath","setDom","isStyleLoading","useLayoutEffect","updateSidebarPositionAndHeight","sidebars","pageTop","domTop","tabs","tabsHeight","scrollbarTopPx","footer","scrollbarEndPx","updateFooterWidth","preRender","rawContent","contentPath","addBaseUrl","updateDom","list","attributeName","elem","elemAttribute","svg","svgContent","unescape","normalizedWindowLocation","mkdocsToggleSidebar","article","toggleSidebar","sourceAnchor","sourceURL","issueTitle","issueDesc","gitUrl","gitInfo","repoPath","feedbackLink","FeedbackOutlinedIcon","postRender","transformedElement","handleMetaRedirects","entityName","determineRedirectURL","metaUrl","normalizedCurrentUrl","absoluteRedirectObj","currentTechDocPath","indexOfSiteHome","metaContentParameters","redirectURL","activeNavItems","activeNavItem","checkbox","lastItem","code","addLinkClickListener","modifierActive","navLabels","keyboardEvent","forId","Event","shouldReplaceContent","preTransformedDomElement","hashElement","useShadowRootElements","selectors","useShadowRoot","setRootNode","observer","MutationObserver","nodeList","handleAppend","newShadowRoot","HeaderLabelContent","typographyRootComponent","HeaderLabel","contentTypograpyRootComponent","skeleton","Skeleton","metadataLoading","site_description","locationMetadata","spec","lifecycle","docsRootLink","labels","CodeIcon","noTdMetadata","noEntMetadata","stringEntityRef","entityDisplayName","techdocsTabTitleItems","removeTrailingSlash","tabTitle","tabTitleItems","lineClamp","asListItem","asLink","ListItemWrapper","resultTitle","resultName","TextItem","__webpack_public_path__"],"mappings":"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"}