@backstage/frontend-app-api 0.7.0 → 0.7.1-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/apis/implementations/ComponentsApi/DefaultComponentsApi.esm.js +10 -33
  3. package/dist/apis/implementations/ComponentsApi/DefaultComponentsApi.esm.js.map +1 -1
  4. package/dist/apis/implementations/IconsApi/DefaultIconsApi.esm.js +4 -24
  5. package/dist/apis/implementations/IconsApi/DefaultIconsApi.esm.js.map +1 -1
  6. package/dist/app-defaults/src/defaults/components.esm.js +1 -1
  7. package/dist/app-defaults/src/defaults/components.esm.js.map +1 -1
  8. package/dist/core-app-api/src/apis/implementations/AppLanguageApi/AppLanguageSelector.esm.js +26 -51
  9. package/dist/core-app-api/src/apis/implementations/AppLanguageApi/AppLanguageSelector.esm.js.map +1 -1
  10. package/dist/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.esm.js +2 -10
  11. package/dist/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.esm.js.map +1 -1
  12. package/dist/core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy.esm.js +10 -37
  13. package/dist/core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy.esm.js.map +1 -1
  14. package/dist/core-app-api/src/apis/implementations/IdentityApi/startCookieAuthRefresh.esm.js +4 -4
  15. package/dist/core-app-api/src/apis/implementations/IdentityApi/startCookieAuthRefresh.esm.js.map +1 -1
  16. package/dist/core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.esm.js +85 -126
  17. package/dist/core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.esm.js.map +1 -1
  18. package/dist/core-app-api/src/app/isProtectedApp.esm.js +1 -2
  19. package/dist/core-app-api/src/app/isProtectedApp.esm.js.map +1 -1
  20. package/dist/core-app-api/src/lib/subjects.esm.js +5 -11
  21. package/dist/core-app-api/src/lib/subjects.esm.js.map +1 -1
  22. package/dist/extensions/AppNav.esm.js +2 -4
  23. package/dist/extensions/AppNav.esm.js.map +1 -1
  24. package/dist/extensions/AppRoot.esm.js +2 -3
  25. package/dist/extensions/AppRoot.esm.js.map +1 -1
  26. package/dist/extensions/components.esm.js +1 -1
  27. package/dist/extensions/components.esm.js.map +1 -1
  28. package/dist/frontend-plugin-api/src/wiring/resolveExtensionDefinition.esm.js +1 -2
  29. package/dist/frontend-plugin-api/src/wiring/resolveExtensionDefinition.esm.js.map +1 -1
  30. package/dist/routing/RouteResolver.esm.js +2 -4
  31. package/dist/routing/RouteResolver.esm.js.map +1 -1
  32. package/dist/routing/RouteTracker.esm.js +7 -11
  33. package/dist/routing/RouteTracker.esm.js.map +1 -1
  34. package/dist/routing/extractRouteInfoFromAppNode.esm.js +5 -6
  35. package/dist/routing/extractRouteInfoFromAppNode.esm.js.map +1 -1
  36. package/dist/routing/getBasePath.esm.js +1 -2
  37. package/dist/routing/getBasePath.esm.js.map +1 -1
  38. package/dist/routing/resolveRouteBindings.esm.js +1 -2
  39. package/dist/routing/resolveRouteBindings.esm.js.map +1 -1
  40. package/dist/tree/instantiateAppNodeTree.esm.js +4 -7
  41. package/dist/tree/instantiateAppNodeTree.esm.js.map +1 -1
  42. package/dist/tree/resolveAppNodeSpecs.esm.js +4 -6
  43. package/dist/tree/resolveAppNodeSpecs.esm.js.map +1 -1
  44. package/dist/tree/resolveAppTree.esm.js +6 -12
  45. package/dist/tree/resolveAppTree.esm.js.map +1 -1
  46. package/dist/wiring/createApp.esm.js +13 -24
  47. package/dist/wiring/createApp.esm.js.map +1 -1
  48. package/dist/wiring/discovery.esm.js +3 -5
  49. package/dist/wiring/discovery.esm.js.map +1 -1
  50. package/package.json +8 -8
@@ -4,29 +4,6 @@ import { toInternalTranslationResource } from '../../../../../core-plugin-api/sr
4
4
  import { toInternalTranslationRef } from '../../../../../core-plugin-api/src/translation/TranslationRef.esm.js';
5
5
  import { DEFAULT_LANGUAGE } from '../AppLanguageApi/AppLanguageSelector.esm.js';
6
6
 
7
- var __accessCheck = (obj, member, msg) => {
8
- if (!member.has(obj))
9
- throw TypeError("Cannot " + msg);
10
- };
11
- var __privateGet = (obj, member, getter) => {
12
- __accessCheck(obj, member, "read from private field");
13
- return member.get(obj);
14
- };
15
- var __privateAdd = (obj, member, value) => {
16
- if (member.has(obj))
17
- throw TypeError("Cannot add the same private member more than once");
18
- member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
19
- };
20
- var __privateSet = (obj, member, value, setter) => {
21
- __accessCheck(obj, member, "write to private field");
22
- member.set(obj, value);
23
- return value;
24
- };
25
- var __privateMethod = (obj, member, method) => {
26
- __accessCheck(obj, member, "access private method");
27
- return method;
28
- };
29
- var _loaded, _loading, _loaders, _getLoaderKey, getLoaderKey_fn, _i18n, _loader, _language, _registeredRefs, _languageChangeListeners, _changeLanguage, changeLanguage_fn, _createSnapshot, createSnapshot_fn, _registerDefaults, registerDefaults_fn;
30
7
  function removeNulls(messages) {
31
8
  return Object.fromEntries(
32
9
  Object.entries(messages).filter(
@@ -37,41 +14,43 @@ function removeNulls(messages) {
37
14
  class ResourceLoader {
38
15
  constructor(onLoad) {
39
16
  this.onLoad = onLoad;
40
- __privateAdd(this, _getLoaderKey);
41
- /** Loaded resources by loader key */
42
- __privateAdd(this, _loaded, /* @__PURE__ */ new Set());
43
- /** Resource loading promises by loader key */
44
- __privateAdd(this, _loading, /* @__PURE__ */ new Map());
45
- /** Loaders for each resource language */
46
- __privateAdd(this, _loaders, /* @__PURE__ */ new Map());
47
17
  }
18
+ /** Loaded resources by loader key */
19
+ #loaded = /* @__PURE__ */ new Set();
20
+ /** Resource loading promises by loader key */
21
+ #loading = /* @__PURE__ */ new Map();
22
+ /** Loaders for each resource language */
23
+ #loaders = /* @__PURE__ */ new Map();
48
24
  addTranslationResource(resource) {
49
25
  const internalResource = toInternalTranslationResource(resource);
50
26
  for (const entry of internalResource.resources) {
51
- const key = __privateMethod(this, _getLoaderKey, getLoaderKey_fn).call(this, entry.language, internalResource.id);
52
- if (!__privateGet(this, _loaders).has(key)) {
53
- __privateGet(this, _loaders).set(key, entry.loader);
27
+ const key = this.#getLoaderKey(entry.language, internalResource.id);
28
+ if (!this.#loaders.has(key)) {
29
+ this.#loaders.set(key, entry.loader);
54
30
  }
55
31
  }
56
32
  }
33
+ #getLoaderKey(language, namespace) {
34
+ return `${language}/${namespace}`;
35
+ }
57
36
  needsLoading(language, namespace) {
58
- const key = __privateMethod(this, _getLoaderKey, getLoaderKey_fn).call(this, language, namespace);
59
- const loader = __privateGet(this, _loaders).get(key);
37
+ const key = this.#getLoaderKey(language, namespace);
38
+ const loader = this.#loaders.get(key);
60
39
  if (!loader) {
61
40
  return false;
62
41
  }
63
- return !__privateGet(this, _loaded).has(key);
42
+ return !this.#loaded.has(key);
64
43
  }
65
44
  async load(language, namespace) {
66
- const key = __privateMethod(this, _getLoaderKey, getLoaderKey_fn).call(this, language, namespace);
67
- const loader = __privateGet(this, _loaders).get(key);
45
+ const key = this.#getLoaderKey(language, namespace);
46
+ const loader = this.#loaders.get(key);
68
47
  if (!loader) {
69
48
  return;
70
49
  }
71
- if (__privateGet(this, _loaded).has(key)) {
50
+ if (this.#loaded.has(key)) {
72
51
  return;
73
52
  }
74
- const loading = __privateGet(this, _loading).get(key);
53
+ const loading = this.#loading.get(key);
75
54
  if (loading) {
76
55
  await loading;
77
56
  return;
@@ -79,40 +58,18 @@ class ResourceLoader {
79
58
  const load = loader().then(
80
59
  (result) => {
81
60
  this.onLoad({ language, namespace, messages: result.messages });
82
- __privateGet(this, _loaded).add(key);
61
+ this.#loaded.add(key);
83
62
  },
84
63
  (error) => {
85
- __privateGet(this, _loaded).add(key);
64
+ this.#loaded.add(key);
86
65
  throw error;
87
66
  }
88
67
  );
89
- __privateGet(this, _loading).set(key, load);
68
+ this.#loading.set(key, load);
90
69
  await load;
91
70
  }
92
71
  }
93
- _loaded = new WeakMap();
94
- _loading = new WeakMap();
95
- _loaders = new WeakMap();
96
- _getLoaderKey = new WeakSet();
97
- getLoaderKey_fn = function(language, namespace) {
98
- return `${language}/${namespace}`;
99
- };
100
- const _I18nextTranslationApi = class _I18nextTranslationApi {
101
- constructor(i18n, loader, language) {
102
- __privateAdd(this, _changeLanguage);
103
- __privateAdd(this, _createSnapshot);
104
- __privateAdd(this, _registerDefaults);
105
- __privateAdd(this, _i18n, void 0);
106
- __privateAdd(this, _loader, void 0);
107
- __privateAdd(this, _language, void 0);
108
- /** Keep track of which refs we have registered default resources for */
109
- __privateAdd(this, _registeredRefs, /* @__PURE__ */ new Set());
110
- /** Notify observers when language changes */
111
- __privateAdd(this, _languageChangeListeners, /* @__PURE__ */ new Set());
112
- __privateSet(this, _i18n, i18n);
113
- __privateSet(this, _loader, loader);
114
- __privateSet(this, _language, language);
115
- }
72
+ class I18nextTranslationApi {
116
73
  static create(options) {
117
74
  const { languages } = options.languageApi.getAvailableLanguages();
118
75
  const i18n = createInstance({
@@ -146,7 +103,7 @@ const _I18nextTranslationApi = class _I18nextTranslationApi {
146
103
  // overwrite translations
147
104
  );
148
105
  });
149
- const resources = (options == null ? void 0 : options.resources) || [];
106
+ const resources = options?.resources || [];
150
107
  for (let i = resources.length - 1; i >= 0; i--) {
151
108
  const resource = resources[i];
152
109
  if (resource.$$type === "@backstage/TranslationResource") {
@@ -163,34 +120,45 @@ const _I18nextTranslationApi = class _I18nextTranslationApi {
163
120
  );
164
121
  }
165
122
  }
166
- const instance = new _I18nextTranslationApi(
123
+ const instance = new I18nextTranslationApi(
167
124
  i18n,
168
125
  loader,
169
126
  options.languageApi.getLanguage().language
170
127
  );
171
128
  options.languageApi.language$().subscribe(({ language }) => {
172
- var _a;
173
- __privateMethod(_a = instance, _changeLanguage, changeLanguage_fn).call(_a, language);
129
+ instance.#changeLanguage(language);
174
130
  });
175
131
  return instance;
176
132
  }
133
+ #i18n;
134
+ #loader;
135
+ #language;
136
+ /** Keep track of which refs we have registered default resources for */
137
+ #registeredRefs = /* @__PURE__ */ new Set();
138
+ /** Notify observers when language changes */
139
+ #languageChangeListeners = /* @__PURE__ */ new Set();
140
+ constructor(i18n, loader, language) {
141
+ this.#i18n = i18n;
142
+ this.#loader = loader;
143
+ this.#language = language;
144
+ }
177
145
  getTranslation(translationRef) {
178
146
  const internalRef = toInternalTranslationRef(translationRef);
179
- __privateMethod(this, _registerDefaults, registerDefaults_fn).call(this, internalRef);
180
- return __privateMethod(this, _createSnapshot, createSnapshot_fn).call(this, internalRef);
147
+ this.#registerDefaults(internalRef);
148
+ return this.#createSnapshot(internalRef);
181
149
  }
182
150
  translation$(translationRef) {
183
151
  const internalRef = toInternalTranslationRef(translationRef);
184
- __privateMethod(this, _registerDefaults, registerDefaults_fn).call(this, internalRef);
152
+ this.#registerDefaults(internalRef);
185
153
  return new ObservableImpl((subscriber) => {
186
154
  let loadTicket = {};
187
155
  const loadResource = () => {
188
156
  loadTicket = {};
189
157
  const ticket = loadTicket;
190
- __privateGet(this, _loader).load(__privateGet(this, _language), internalRef.id).then(
158
+ this.#loader.load(this.#language, internalRef.id).then(
191
159
  () => {
192
160
  if (ticket === loadTicket) {
193
- const snapshot = __privateMethod(this, _createSnapshot, createSnapshot_fn).call(this, internalRef);
161
+ const snapshot = this.#createSnapshot(internalRef);
194
162
  if (snapshot.ready) {
195
163
  subscriber.next(snapshot);
196
164
  }
@@ -204,72 +172,63 @@ const _I18nextTranslationApi = class _I18nextTranslationApi {
204
172
  );
205
173
  };
206
174
  const onChange = () => {
207
- const snapshot = __privateMethod(this, _createSnapshot, createSnapshot_fn).call(this, internalRef);
175
+ const snapshot = this.#createSnapshot(internalRef);
208
176
  if (snapshot.ready) {
209
177
  subscriber.next(snapshot);
210
178
  } else {
211
179
  loadResource();
212
180
  }
213
181
  };
214
- if (__privateGet(this, _loader).needsLoading(__privateGet(this, _language), internalRef.id)) {
182
+ if (this.#loader.needsLoading(this.#language, internalRef.id)) {
215
183
  loadResource();
216
184
  }
217
- __privateGet(this, _languageChangeListeners).add(onChange);
185
+ this.#languageChangeListeners.add(onChange);
218
186
  return () => {
219
- __privateGet(this, _languageChangeListeners).delete(onChange);
187
+ this.#languageChangeListeners.delete(onChange);
220
188
  };
221
189
  });
222
190
  }
223
- };
224
- _i18n = new WeakMap();
225
- _loader = new WeakMap();
226
- _language = new WeakMap();
227
- _registeredRefs = new WeakMap();
228
- _languageChangeListeners = new WeakMap();
229
- _changeLanguage = new WeakSet();
230
- changeLanguage_fn = function(language) {
231
- if (__privateGet(this, _language) !== language) {
232
- __privateSet(this, _language, language);
233
- __privateGet(this, _i18n).changeLanguage(language);
234
- __privateGet(this, _languageChangeListeners).forEach((listener) => listener());
235
- }
236
- };
237
- _createSnapshot = new WeakSet();
238
- createSnapshot_fn = function(internalRef) {
239
- if (__privateGet(this, _loader).needsLoading(__privateGet(this, _language), internalRef.id)) {
240
- return { ready: false };
191
+ #changeLanguage(language) {
192
+ if (this.#language !== language) {
193
+ this.#language = language;
194
+ this.#i18n.changeLanguage(language);
195
+ this.#languageChangeListeners.forEach((listener) => listener());
196
+ }
241
197
  }
242
- const t = __privateGet(this, _i18n).getFixedT(
243
- null,
244
- internalRef.id
245
- );
246
- return {
247
- ready: true,
248
- t
249
- };
250
- };
251
- _registerDefaults = new WeakSet();
252
- registerDefaults_fn = function(internalRef) {
253
- if (__privateGet(this, _registeredRefs).has(internalRef.id)) {
254
- return;
198
+ #createSnapshot(internalRef) {
199
+ if (this.#loader.needsLoading(this.#language, internalRef.id)) {
200
+ return { ready: false };
201
+ }
202
+ const t = this.#i18n.getFixedT(
203
+ null,
204
+ internalRef.id
205
+ );
206
+ return {
207
+ ready: true,
208
+ t
209
+ };
255
210
  }
256
- __privateGet(this, _registeredRefs).add(internalRef.id);
257
- const defaultMessages = internalRef.getDefaultMessages();
258
- __privateGet(this, _i18n).addResourceBundle(
259
- DEFAULT_LANGUAGE,
260
- internalRef.id,
261
- defaultMessages,
262
- true,
263
- // merge with existing translations
264
- false
265
- // do not overwrite translations
266
- );
267
- const defaultResource = internalRef.getDefaultResource();
268
- if (defaultResource) {
269
- __privateGet(this, _loader).addTranslationResource(defaultResource);
211
+ #registerDefaults(internalRef) {
212
+ if (this.#registeredRefs.has(internalRef.id)) {
213
+ return;
214
+ }
215
+ this.#registeredRefs.add(internalRef.id);
216
+ const defaultMessages = internalRef.getDefaultMessages();
217
+ this.#i18n.addResourceBundle(
218
+ DEFAULT_LANGUAGE,
219
+ internalRef.id,
220
+ defaultMessages,
221
+ true,
222
+ // merge with existing translations
223
+ false
224
+ // do not overwrite translations
225
+ );
226
+ const defaultResource = internalRef.getDefaultResource();
227
+ if (defaultResource) {
228
+ this.#loader.addTranslationResource(defaultResource);
229
+ }
270
230
  }
271
- };
272
- let I18nextTranslationApi = _I18nextTranslationApi;
231
+ }
273
232
 
274
233
  export { I18nextTranslationApi };
275
234
  //# sourceMappingURL=I18nextTranslationApi.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"I18nextTranslationApi.esm.js","sources":["../../../../../../../core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AppLanguageApi,\n TranslationApi,\n TranslationFunction,\n TranslationMessages,\n TranslationRef,\n TranslationResource,\n TranslationSnapshot,\n} from '@backstage/core-plugin-api/alpha';\nimport { createInstance as createI18n, type i18n as I18n } 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';\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/** @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 },\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 { 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 );\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\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(i18n: I18n, loader: ResourceLoader, language: string) {\n this.#i18n = i18n;\n this.#loader = loader;\n this.#language = language;\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 t = this.#i18n.getFixedT(\n null,\n internalRef.id,\n ) as TranslationFunction<TMessages>;\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"],"names":["createI18n"],"mappings":"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"}
1
+ {"version":3,"file":"I18nextTranslationApi.esm.js","sources":["../../../../../../../core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AppLanguageApi,\n TranslationApi,\n TranslationFunction,\n TranslationMessages,\n TranslationRef,\n TranslationResource,\n TranslationSnapshot,\n} from '@backstage/core-plugin-api/alpha';\nimport { createInstance as createI18n, type i18n as I18n } 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';\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/** @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 },\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 { 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 );\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\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(i18n: I18n, loader: ResourceLoader, language: string) {\n this.#i18n = i18n;\n this.#loader = loader;\n this.#language = language;\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 t = this.#i18n.getFixedT(\n null,\n internalRef.id,\n ) as TranslationFunction<TMessages>;\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"],"names":["createI18n"],"mappings":"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"}
@@ -1,7 +1,6 @@
1
1
  function isProtectedApp() {
2
- var _a;
3
2
  const element = document.querySelector('meta[name="backstage-app-mode"]');
4
- const appMode = (_a = element == null ? void 0 : element.getAttribute("content")) != null ? _a : "public";
3
+ const appMode = element?.getAttribute("content") ?? "public";
5
4
  return appMode === "protected";
6
5
  }
7
6
 
@@ -1 +1 @@
1
- {"version":3,"file":"isProtectedApp.esm.js","sources":["../../../../../core-app-api/src/app/isProtectedApp.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\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"],"names":[],"mappings":"AAgBO,SAAS,cAAiB,GAAA;AAhBjC,EAAA,IAAA,EAAA,CAAA;AAiBE,EAAM,MAAA,OAAA,GAAU,QAAS,CAAA,aAAA,CAAc,iCAAiC,CAAA,CAAA;AACxE,EAAA,MAAM,OAAU,GAAA,CAAA,EAAA,GAAA,OAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,OAAA,CAAS,YAAa,CAAA,SAAA,CAAA,KAAtB,IAAoC,GAAA,EAAA,GAAA,QAAA,CAAA;AACpD,EAAA,OAAO,OAAY,KAAA,WAAA,CAAA;AACrB;;;;"}
1
+ {"version":3,"file":"isProtectedApp.esm.js","sources":["../../../../../core-app-api/src/app/isProtectedApp.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\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"],"names":[],"mappings":"AAgBO,SAAS,cAAiB,GAAA;AAC/B,EAAM,MAAA,OAAA,GAAU,QAAS,CAAA,aAAA,CAAc,iCAAiC,CAAA,CAAA;AACxE,EAAA,MAAM,OAAU,GAAA,OAAA,EAAS,YAAa,CAAA,SAAS,CAAK,IAAA,QAAA,CAAA;AACpD,EAAA,OAAO,OAAY,KAAA,WAAA,CAAA;AACrB;;;;"}
@@ -1,18 +1,11 @@
1
1
  import ObservableImpl from 'zen-observable';
2
2
 
3
- var __defProp = Object.defineProperty;
4
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
5
- var __publicField = (obj, key, value) => {
6
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
7
- return value;
8
- };
9
3
  class BehaviorSubject {
4
+ isClosed;
5
+ currentValue;
6
+ terminatingError;
7
+ observable;
10
8
  constructor(value) {
11
- __publicField(this, "isClosed");
12
- __publicField(this, "currentValue");
13
- __publicField(this, "terminatingError");
14
- __publicField(this, "observable");
15
- __publicField(this, "subscribers", /* @__PURE__ */ new Set());
16
9
  this.isClosed = false;
17
10
  this.currentValue = value;
18
11
  this.terminatingError = void 0;
@@ -33,6 +26,7 @@ class BehaviorSubject {
33
26
  };
34
27
  });
35
28
  }
29
+ subscribers = /* @__PURE__ */ new Set();
36
30
  [Symbol.observable]() {
37
31
  return this;
38
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"subjects.esm.js","sources":["../../../../../core-app-api/src/lib/subjects.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { 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"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"subjects.esm.js","sources":["../../../../../core-app-api/src/lib/subjects.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { 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"],"names":[],"mappings":"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"}
@@ -20,10 +20,9 @@ const useSidebarLogoStyles = makeStyles({
20
20
  }
21
21
  });
22
22
  const SidebarLogo = (props) => {
23
- var _a, _b;
24
23
  const classes = useSidebarLogoStyles();
25
24
  const { isOpen } = useSidebarOpenState();
26
- return /* @__PURE__ */ React.createElement("div", { className: classes.root }, /* @__PURE__ */ React.createElement(Link, { to: "/", underline: "none", className: classes.link, "aria-label": "Home" }, isOpen ? (_a = props == null ? void 0 : props.logoFull) != null ? _a : /* @__PURE__ */ React.createElement(LogoFull, null) : (_b = props == null ? void 0 : props.logoIcon) != null ? _b : /* @__PURE__ */ React.createElement(LogoIcon, null)));
25
+ return /* @__PURE__ */ React.createElement("div", { className: classes.root }, /* @__PURE__ */ React.createElement(Link, { to: "/", underline: "none", className: classes.link, "aria-label": "Home" }, isOpen ? props?.logoFull ?? /* @__PURE__ */ React.createElement(LogoFull, null) : props?.logoIcon ?? /* @__PURE__ */ React.createElement(LogoIcon, null)));
27
26
  };
28
27
  const SidebarNavItem = (props) => {
29
28
  const { icon: Icon, title, routeRef } = props;
@@ -52,9 +51,8 @@ const AppNav = createExtension({
52
51
  element: coreExtensionData.reactElement
53
52
  },
54
53
  factory({ inputs }) {
55
- var _a;
56
54
  return {
57
- element: /* @__PURE__ */ React.createElement(Sidebar, null, /* @__PURE__ */ React.createElement(SidebarLogo, { ...(_a = inputs.logos) == null ? void 0 : _a.output.elements }), /* @__PURE__ */ React.createElement(SidebarDivider, null), inputs.items.map((item, index) => /* @__PURE__ */ React.createElement(SidebarNavItem, { ...item.output.target, key: index })))
55
+ element: /* @__PURE__ */ React.createElement(Sidebar, null, /* @__PURE__ */ React.createElement(SidebarLogo, { ...inputs.logos?.output.elements }), /* @__PURE__ */ React.createElement(SidebarDivider, null), inputs.items.map((item, index) => /* @__PURE__ */ React.createElement(SidebarNavItem, { ...item.output.target, key: index })))
58
56
  };
59
57
  }
60
58
  });
@@ -1 +1 @@
1
- {"version":3,"file":"AppNav.esm.js","sources":["../../src/extensions/AppNav.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport {\n createExtension,\n coreExtensionData,\n createExtensionInput,\n useRouteRef,\n createNavItemExtension,\n createNavLogoExtension,\n} from '@backstage/frontend-plugin-api';\nimport { makeStyles } from '@material-ui/core/styles';\nimport {\n Sidebar,\n useSidebarOpenState,\n Link,\n sidebarConfig,\n SidebarDivider,\n SidebarItem,\n} from '@backstage/core-components';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport LogoIcon from '../../../app/src/components/Root/LogoIcon';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport LogoFull from '../../../app/src/components/Root/LogoFull';\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 props: (typeof createNavLogoExtension.logoElementsDataRef)['T'],\n) => {\n const classes = useSidebarLogoStyles();\n const { isOpen } = useSidebarOpenState();\n\n return (\n <div className={classes.root}>\n <Link to=\"/\" underline=\"none\" className={classes.link} aria-label=\"Home\">\n {isOpen\n ? props?.logoFull ?? <LogoFull />\n : props?.logoIcon ?? <LogoIcon />}\n </Link>\n </div>\n );\n};\n\nconst SidebarNavItem = (\n props: (typeof createNavItemExtension.targetDataRef)['T'],\n) => {\n const { icon: Icon, title, routeRef } = props;\n const to = useRouteRef(routeRef)();\n // TODO: Support opening modal, for example, the search one\n return <SidebarItem to={to} icon={Icon} text={title} />;\n};\n\nexport const AppNav = createExtension({\n namespace: 'app',\n name: 'nav',\n attachTo: { id: 'app/layout', input: 'nav' },\n inputs: {\n items: createExtensionInput({\n target: createNavItemExtension.targetDataRef,\n }),\n logos: createExtensionInput(\n {\n elements: createNavLogoExtension.logoElementsDataRef,\n },\n {\n singleton: true,\n optional: true,\n },\n ),\n },\n output: {\n element: coreExtensionData.reactElement,\n },\n factory({ inputs }) {\n return {\n element: (\n <Sidebar>\n <SidebarLogo {...inputs.logos?.output.elements} />\n <SidebarDivider />\n {inputs.items.map((item, index) => (\n <SidebarNavItem {...item.output.target} key={index} />\n ))}\n </Sidebar>\n ),\n };\n },\n});\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AppNav.esm.js","sources":["../../src/extensions/AppNav.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport {\n createExtension,\n coreExtensionData,\n createExtensionInput,\n useRouteRef,\n createNavItemExtension,\n createNavLogoExtension,\n} from '@backstage/frontend-plugin-api';\nimport { makeStyles } from '@material-ui/core/styles';\nimport {\n Sidebar,\n useSidebarOpenState,\n Link,\n sidebarConfig,\n SidebarDivider,\n SidebarItem,\n} from '@backstage/core-components';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport LogoIcon from '../../../app/src/components/Root/LogoIcon';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport LogoFull from '../../../app/src/components/Root/LogoFull';\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 props: (typeof createNavLogoExtension.logoElementsDataRef)['T'],\n) => {\n const classes = useSidebarLogoStyles();\n const { isOpen } = useSidebarOpenState();\n\n return (\n <div className={classes.root}>\n <Link to=\"/\" underline=\"none\" className={classes.link} aria-label=\"Home\">\n {isOpen\n ? props?.logoFull ?? <LogoFull />\n : props?.logoIcon ?? <LogoIcon />}\n </Link>\n </div>\n );\n};\n\nconst SidebarNavItem = (\n props: (typeof createNavItemExtension.targetDataRef)['T'],\n) => {\n const { icon: Icon, title, routeRef } = props;\n const to = useRouteRef(routeRef)();\n // TODO: Support opening modal, for example, the search one\n return <SidebarItem to={to} icon={Icon} text={title} />;\n};\n\nexport const AppNav = createExtension({\n namespace: 'app',\n name: 'nav',\n attachTo: { id: 'app/layout', input: 'nav' },\n inputs: {\n items: createExtensionInput({\n target: createNavItemExtension.targetDataRef,\n }),\n logos: createExtensionInput(\n {\n elements: createNavLogoExtension.logoElementsDataRef,\n },\n {\n singleton: true,\n optional: true,\n },\n ),\n },\n output: {\n element: coreExtensionData.reactElement,\n },\n factory({ inputs }) {\n return {\n element: (\n <Sidebar>\n <SidebarLogo {...inputs.logos?.output.elements} />\n <SidebarDivider />\n {inputs.items.map((item, index) => (\n <SidebarNavItem {...item.output.target} key={index} />\n ))}\n </Sidebar>\n ),\n };\n },\n});\n"],"names":[],"mappings":"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"}
@@ -34,7 +34,6 @@ const AppRoot = createExtension({
34
34
  element: coreExtensionData.reactElement
35
35
  },
36
36
  factory({ inputs }) {
37
- var _a, _b;
38
37
  let content = /* @__PURE__ */ React.createElement(React.Fragment, null, inputs.elements.map((el) => /* @__PURE__ */ React.createElement(Fragment, { key: el.node.spec.id }, el.output.element)), inputs.children.output.element);
39
38
  for (const wrapper of inputs.wrappers) {
40
39
  content = /* @__PURE__ */ React.createElement(wrapper.output.component, null, content);
@@ -43,8 +42,8 @@ const AppRoot = createExtension({
43
42
  element: /* @__PURE__ */ React.createElement(
44
43
  AppRouter,
45
44
  {
46
- SignInPageComponent: (_a = inputs.signInPage) == null ? void 0 : _a.output.component,
47
- RouterComponent: (_b = inputs.router) == null ? void 0 : _b.output.component
45
+ SignInPageComponent: inputs.signInPage?.output.component,
46
+ RouterComponent: inputs.router?.output.component
48
47
  },
49
48
  content
50
49
  )
@@ -1 +1 @@
1
- {"version":3,"file":"AppRoot.esm.js","sources":["../../src/extensions/AppRoot.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, {\n ComponentType,\n Fragment,\n PropsWithChildren,\n ReactNode,\n useContext,\n useState,\n} from 'react';\nimport {\n coreExtensionData,\n createAppRootWrapperExtension,\n createExtension,\n createExtensionInput,\n createRouterExtension,\n createSignInPageExtension,\n} from '@backstage/frontend-plugin-api';\nimport {\n IdentityApi,\n SignInPageProps,\n configApiRef,\n useApi,\n} from '@backstage/core-plugin-api';\nimport { InternalAppContext } from '../wiring/InternalAppContext';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { AppIdentityProxy } from '../../../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy';\nimport { BrowserRouter } from 'react-router-dom';\nimport { RouteTracker } from '../routing/RouteTracker';\nimport { getBasePath } from '../routing/getBasePath';\n\nexport const AppRoot = createExtension({\n namespace: 'app',\n name: 'root',\n attachTo: { id: 'app', input: 'root' },\n inputs: {\n router: createExtensionInput(\n { component: createRouterExtension.componentDataRef },\n { singleton: true, optional: true },\n ),\n signInPage: createExtensionInput(\n { component: createSignInPageExtension.componentDataRef },\n { singleton: true, optional: true },\n ),\n children: createExtensionInput(\n { element: coreExtensionData.reactElement },\n { singleton: true },\n ),\n elements: createExtensionInput({\n element: coreExtensionData.reactElement,\n }),\n wrappers: createExtensionInput({\n component: createAppRootWrapperExtension.componentDataRef,\n }),\n },\n output: {\n element: coreExtensionData.reactElement,\n },\n factory({ inputs }) {\n let content: React.ReactNode = (\n <>\n {inputs.elements.map(el => (\n <Fragment key={el.node.spec.id}>{el.output.element}</Fragment>\n ))}\n {inputs.children.output.element}\n </>\n );\n\n for (const wrapper of inputs.wrappers) {\n content = <wrapper.output.component>{content}</wrapper.output.component>;\n }\n\n return {\n element: (\n <AppRouter\n SignInPageComponent={inputs.signInPage?.output.component}\n RouterComponent={inputs.router?.output.component}\n >\n {content}\n </AppRouter>\n ),\n };\n },\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 = getBasePath(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 SignInPageComponent?: ComponentType<SignInPageProps>;\n RouterComponent?: ComponentType<PropsWithChildren<{}>>;\n}\n\nfunction DefaultRouter(props: PropsWithChildren<{}>) {\n const configApi = useApi(configApiRef);\n const basePath = getBasePath(configApi);\n return <BrowserRouter basename={basePath}>{props.children}</BrowserRouter>;\n}\n\n/**\n * App router and sign-in page wrapper.\n *\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 {\n children,\n SignInPageComponent,\n RouterComponent = DefaultRouter,\n } = props;\n\n const configApi = useApi(configApiRef);\n const basePath = getBasePath(configApi);\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 return (\n <RouterComponent>\n <RouteTracker routeObjects={routeObjects} />\n {children}\n </RouterComponent>\n );\n }\n\n return (\n <RouterComponent>\n <RouteTracker routeObjects={routeObjects} />\n <SignInPageWrapper\n component={SignInPageComponent}\n appIdentityProxy={appIdentityProxy}\n >\n {children}\n </SignInPageWrapper>\n </RouterComponent>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AppRoot.esm.js","sources":["../../src/extensions/AppRoot.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, {\n ComponentType,\n Fragment,\n PropsWithChildren,\n ReactNode,\n useContext,\n useState,\n} from 'react';\nimport {\n coreExtensionData,\n createAppRootWrapperExtension,\n createExtension,\n createExtensionInput,\n createRouterExtension,\n createSignInPageExtension,\n} from '@backstage/frontend-plugin-api';\nimport {\n IdentityApi,\n SignInPageProps,\n configApiRef,\n useApi,\n} from '@backstage/core-plugin-api';\nimport { InternalAppContext } from '../wiring/InternalAppContext';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { AppIdentityProxy } from '../../../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy';\nimport { BrowserRouter } from 'react-router-dom';\nimport { RouteTracker } from '../routing/RouteTracker';\nimport { getBasePath } from '../routing/getBasePath';\n\nexport const AppRoot = createExtension({\n namespace: 'app',\n name: 'root',\n attachTo: { id: 'app', input: 'root' },\n inputs: {\n router: createExtensionInput(\n { component: createRouterExtension.componentDataRef },\n { singleton: true, optional: true },\n ),\n signInPage: createExtensionInput(\n { component: createSignInPageExtension.componentDataRef },\n { singleton: true, optional: true },\n ),\n children: createExtensionInput(\n { element: coreExtensionData.reactElement },\n { singleton: true },\n ),\n elements: createExtensionInput({\n element: coreExtensionData.reactElement,\n }),\n wrappers: createExtensionInput({\n component: createAppRootWrapperExtension.componentDataRef,\n }),\n },\n output: {\n element: coreExtensionData.reactElement,\n },\n factory({ inputs }) {\n let content: React.ReactNode = (\n <>\n {inputs.elements.map(el => (\n <Fragment key={el.node.spec.id}>{el.output.element}</Fragment>\n ))}\n {inputs.children.output.element}\n </>\n );\n\n for (const wrapper of inputs.wrappers) {\n content = <wrapper.output.component>{content}</wrapper.output.component>;\n }\n\n return {\n element: (\n <AppRouter\n SignInPageComponent={inputs.signInPage?.output.component}\n RouterComponent={inputs.router?.output.component}\n >\n {content}\n </AppRouter>\n ),\n };\n },\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 = getBasePath(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 SignInPageComponent?: ComponentType<SignInPageProps>;\n RouterComponent?: ComponentType<PropsWithChildren<{}>>;\n}\n\nfunction DefaultRouter(props: PropsWithChildren<{}>) {\n const configApi = useApi(configApiRef);\n const basePath = getBasePath(configApi);\n return <BrowserRouter basename={basePath}>{props.children}</BrowserRouter>;\n}\n\n/**\n * App router and sign-in page wrapper.\n *\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 {\n children,\n SignInPageComponent,\n RouterComponent = DefaultRouter,\n } = props;\n\n const configApi = useApi(configApiRef);\n const basePath = getBasePath(configApi);\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 return (\n <RouterComponent>\n <RouteTracker routeObjects={routeObjects} />\n {children}\n </RouterComponent>\n );\n }\n\n return (\n <RouterComponent>\n <RouteTracker routeObjects={routeObjects} />\n <SignInPageWrapper\n component={SignInPageComponent}\n appIdentityProxy={appIdentityProxy}\n >\n {children}\n </SignInPageWrapper>\n </RouterComponent>\n );\n}\n"],"names":[],"mappings":"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"}