@backstage/core-plugin-api 1.6.0-next.2 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @backstage/core-plugin-api
2
2
 
3
+ ## 1.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 18619f793c94: Added the optional `expiresAt` field that may now be part of a `BackstageIdentityResponse`.
8
+ - 6e30769cc627: Introduced experimental support for internationalization.
9
+
10
+ ### Patch Changes
11
+
12
+ - 406b786a2a2c: Mark package as being free of side effects, allowing more optimized Webpack builds.
13
+ - 8cec7664e146: Removed `@types/node` dependency
14
+ - Updated dependencies
15
+ - @backstage/config@1.1.0
16
+ - @backstage/types@1.1.1
17
+ - @backstage/version-bridge@1.0.5
18
+
19
+ ## 1.6.0-next.3
20
+
21
+ ### Patch Changes
22
+
23
+ - 406b786a2a2c: Mark package as being free of side effects, allowing more optimized Webpack builds.
24
+ - Updated dependencies
25
+ - @backstage/config@1.1.0-next.2
26
+ - @backstage/types@1.1.1-next.0
27
+ - @backstage/version-bridge@1.0.5-next.0
28
+
3
29
  ## 1.6.0-next.2
4
30
 
5
31
  ### Minor Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/core-plugin-api",
3
- "version": "1.6.0-next.2",
3
+ "version": "1.6.0",
4
4
  "main": "../dist/alpha.esm.js",
5
5
  "module": "../dist/alpha.esm.js",
6
6
  "types": "../dist/alpha.d.ts"
package/dist/alpha.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { BackstagePlugin, ApiRef } from '@backstage/core-plugin-api';
2
2
  import { ReactNode } from 'react';
3
- import { i18n } from 'i18next';
3
+ import { TranslationRef as TranslationRef$1, TranslationMessages as TranslationMessages$1 } from '@backstage/core-plugin-api/alpha';
4
+ import { Observable } from '@backstage/types';
4
5
 
5
6
  /**
6
7
  * Properties for the PluginProvider component.
@@ -25,54 +26,393 @@ declare const PluginProvider: (props: PluginOptionsProviderProps) => JSX.Element
25
26
  */
26
27
  declare function usePluginOptions<TPluginOptions extends {} = {}>(): TPluginOptions;
27
28
 
29
+ /**
30
+ * Represents a collection of messages to be provided for a given translation ref.
31
+ *
32
+ * @alpha
33
+ * @remarks
34
+ *
35
+ * This collection of messages can either be used directly as an override for the
36
+ * default messages, or it can be used to provide translations for a language by
37
+ * by being referenced by a {@link TranslationResource}.
38
+ */
39
+ interface TranslationMessages<TId extends string = string, TMessages extends {
40
+ [key in string]: string;
41
+ } = {
42
+ [key in string]: string;
43
+ }, TFull extends boolean = boolean> {
44
+ $$type: '@backstage/TranslationMessages';
45
+ /** The ID of the translation ref that these messages are for */
46
+ id: TId;
47
+ /** Whether or not these messages override all known messages */
48
+ full: TFull;
49
+ /** The messages provided for the given translation ref */
50
+ messages: TMessages;
51
+ }
52
+ /**
53
+ * Options for {@link createTranslationMessages}.
54
+ *
55
+ * @alpha
56
+ */
57
+ interface TranslationMessagesOptions<TId extends string, TMessages extends {
58
+ [key in string]: string;
59
+ }, TFull extends boolean> {
60
+ ref: TranslationRef$1<TId, TMessages>;
61
+ full?: TFull;
62
+ messages: false extends TFull ? {
63
+ [key in keyof TMessages]?: string | null;
64
+ } : {
65
+ [key in keyof TMessages]: string | null;
66
+ };
67
+ }
68
+ /**
69
+ * Creates a collection of messages for a given translation ref.
70
+ *
71
+ * @alpha
72
+ */
73
+ declare function createTranslationMessages<TId extends string, TMessages extends {
74
+ [key in string]: string;
75
+ }, TFull extends boolean>(options: TranslationMessagesOptions<TId, TMessages, TFull>): TranslationMessages<TId, TMessages, TFull>;
76
+
28
77
  /** @alpha */
29
- interface TranslationRefConfig<Messages extends Record<keyof Messages, string>> {
30
- id: string;
31
- messages: Messages;
32
- lazyResources?: Record<string, () => Promise<{
33
- messages: Messages;
34
- }>>;
35
- resources?: Record<string, Messages>;
78
+ interface TranslationResource<TId extends string = string> {
79
+ $$type: '@backstage/TranslationResource';
80
+ id: TId;
36
81
  }
37
82
  /** @alpha */
38
- interface TranslationRef<Messages extends Record<keyof Messages, string> = Record<string, string>> {
39
- getId(): string;
40
- getDefaultMessages(): Messages;
41
- getResources(): Record<string, Messages> | undefined;
42
- getLazyResources(): Record<string, () => Promise<{
43
- messages: Messages;
44
- }>> | undefined;
83
+ interface TranslationResourceOptions<TId extends string, TMessages extends {
84
+ [key in string]: string;
85
+ }, TTranslations extends {
86
+ [language in string]: () => Promise<{
87
+ default: TranslationMessages$1<TId> | {
88
+ [key in keyof TMessages]: string | null;
89
+ };
90
+ }>;
91
+ }> {
92
+ ref: TranslationRef$1<TId, TMessages>;
93
+ translations: TTranslations;
45
94
  }
46
95
  /** @alpha */
47
- type TranslationOptions<Messages extends Record<keyof Messages, string> = Record<string, string>> = Messages;
96
+ declare function createTranslationResource<TId extends string, TMessages extends {
97
+ [key in string]: string;
98
+ }, TTranslations extends {
99
+ [language in string]: () => Promise<{
100
+ default: TranslationMessages$1<TId> | {
101
+ [key in keyof TMessages]: string | null;
102
+ };
103
+ }>;
104
+ }>(options: TranslationResourceOptions<TId, TMessages, TTranslations>): TranslationResource<TId>;
48
105
 
49
106
  /** @alpha */
50
- declare class TranslationRefImpl<Messages extends Record<keyof Messages, string>> implements TranslationRef<Messages> {
51
- private readonly config;
52
- static create<Messages extends Record<keyof Messages, string>>(config: TranslationRefConfig<Messages>): TranslationRefImpl<Messages>;
53
- getId(): string;
54
- getDefaultMessages(): Messages;
55
- getLazyResources(): Record<string, () => Promise<{
56
- messages: Messages;
57
- }>> | undefined;
58
- getResources(): Record<string, Messages> | undefined;
59
- toString(): string;
60
- private constructor();
107
+ interface TranslationRef<TId extends string = string, TMessages extends {
108
+ [key in string]: string;
109
+ } = {
110
+ [key in string]: string;
111
+ }> {
112
+ $$type: '@backstage/TranslationRef';
113
+ id: TId;
114
+ T: TMessages;
61
115
  }
62
116
  /** @alpha */
63
- declare const createTranslationRef: <Messages extends Record<keyof Messages, string> = {}>(config: TranslationRefConfig<Messages>) => TranslationRef<Messages>;
117
+ interface TranslationRefOptions<TId extends string, TMessages extends {
118
+ [key in string]: string;
119
+ }, TTranslations extends {
120
+ [language in string]: () => Promise<{
121
+ default: {
122
+ [key in keyof TMessages]: string | null;
123
+ };
124
+ }>;
125
+ }> {
126
+ id: TId;
127
+ messages: TMessages;
128
+ translations?: TTranslations;
129
+ }
130
+ /** @alpha */
131
+ declare function createTranslationRef<TId extends string, const TMessages extends {
132
+ [key in string]: string;
133
+ }, TTranslations extends {
134
+ [language in string]: () => Promise<{
135
+ default: {
136
+ [key in keyof TMessages]: string | null;
137
+ };
138
+ }>;
139
+ }>(config: TranslationRefOptions<TId, TMessages, TTranslations>): TranslationRef<TId, TMessages>;
64
140
 
141
+ /**
142
+ * Base translation options.
143
+ *
144
+ * @alpha
145
+ */
146
+ interface BaseOptions {
147
+ interpolation?: {
148
+ /** Whether to HTML escape provided values, defaults to false */
149
+ escapeValue?: boolean;
150
+ };
151
+ }
152
+ /**
153
+ * All pluralization suffixes supported by i18next
154
+ *
155
+ * @ignore
156
+ */
157
+ type TranslationPlural = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other';
158
+ /**
159
+ * A mapping of i18n formatting types to their corresponding types and options.
160
+ * @ignore
161
+ */
162
+ type I18nextFormatMap = {
163
+ number: {
164
+ type: number;
165
+ options: Intl.NumberFormatOptions;
166
+ };
167
+ currency: {
168
+ type: number;
169
+ options: Intl.NumberFormatOptions;
170
+ };
171
+ datetime: {
172
+ type: Date;
173
+ options: Intl.DateTimeFormatOptions;
174
+ };
175
+ relativetime: {
176
+ type: number;
177
+ options: {
178
+ range?: Intl.RelativeTimeFormatUnit;
179
+ } & Intl.RelativeTimeFormatOptions;
180
+ };
181
+ list: {
182
+ type: string[];
183
+ options: Intl.ListFormatOptions;
184
+ };
185
+ };
186
+ /**
187
+ * Extracts all pluralized keys from the message map.
188
+ *
189
+ * @example
190
+ * ```
191
+ * { foo: 'foo', bar_one: 'bar', bar_other: 'bars' } -> 'bar'
192
+ * ```
193
+ *
194
+ * @ignore
195
+ */
196
+ type PluralKeys<TMessages extends {
197
+ [key in string]: string;
198
+ }> = {
199
+ [Key in keyof TMessages]: Key extends `${infer K}_${TranslationPlural}` ? K : never;
200
+ }[keyof TMessages];
201
+ /**
202
+ * Collapses a message map into normalized keys with union values.
203
+ *
204
+ * @example
205
+ * ```
206
+ * { foo_one: 'foo', foo_other: 'foos' } -> { foo: 'foo' | 'foos' }
207
+ * ```
208
+ *
209
+ * @ignore
210
+ */
211
+ type CollapsedMessages<TMessages extends {
212
+ [key in string]: string;
213
+ }> = {
214
+ [key in keyof TMessages as key extends `${infer K}_${TranslationPlural}` ? K : key]: TMessages[key];
215
+ };
216
+ /**
217
+ * Helper type that expands type hints
218
+ *
219
+ * @ignore
220
+ */
221
+ type Expand<T> = T extends infer O ? {
222
+ [K in keyof O]: O[K];
223
+ } : never;
224
+ /**
225
+ * Helper type that expands type hints recursively
226
+ *
227
+ * @ignore
228
+ */
229
+ type ExpandRecursive<T> = T extends infer O ? {
230
+ [K in keyof O]: ExpandRecursive<O[K]>;
231
+ } : never;
232
+ /**
233
+ * Trim away whitespace
234
+ *
235
+ * @ignore
236
+ */
237
+ type Trim<T> = T extends ` ${infer U}` ? Trim<U> : T extends `${infer U} ` ? Trim<U> : T;
238
+ /**
239
+ * Extracts the key and format from a replacement string.
240
+ *
241
+ * @example
242
+ * ```
243
+ * 'foo, number' -> { foo: number }, 'foo' -> { foo: undefined }
244
+ * ```
245
+ */
246
+ type ExtractFormat<Replacement extends string> = Replacement extends `${infer Key},${infer FullFormat}` ? {
247
+ [key in Trim<Key>]: Lowercase<Trim<FullFormat extends `${infer Format}(${string})${string}` ? Format : FullFormat>>;
248
+ } : {
249
+ [key in Trim<Replacement>]: undefined;
250
+ };
251
+ /**
252
+ * Expand the keys in a flat map to nested objects.
253
+ *
254
+ * @example
255
+ * ```
256
+ * { 'a.b': 'foo', 'a.c': 'bar' } -> { a: { b: 'foo', c: 'bar' }
257
+ * ```
258
+ *
259
+ * @ignore
260
+ */
261
+ type ExpandKeys<TMap extends {}> = {
262
+ [Key in keyof TMap as Key extends `${infer Prefix}.${string}` ? Prefix : Key]: Key extends `${string}.${infer Rest}` ? ExpandKeys<{
263
+ [key in Rest]: TMap[Key];
264
+ }> : TMap[Key];
265
+ };
266
+ /**
267
+ * Extracts all option keys and their format from a message string.
268
+ *
269
+ * @example
270
+ * ```
271
+ * 'foo {{bar}} {{baz, number}}' -> { 'bar': undefined, 'baz': 'number' }
272
+ * ```
273
+ *
274
+ * @ignore
275
+ */
276
+ type ReplaceFormatsFromMessage<TMessage> = TMessage extends `${string}{{${infer Replacement}}}${infer Tail}` ? ExpandKeys<ExtractFormat<Replacement>> & ReplaceFormatsFromMessage<Tail> : {};
277
+ /**
278
+ * Generates the replace options structure
279
+ *
280
+ * @ignore
281
+ */
282
+ type ReplaceOptionsFromFormats<TFormats extends {}> = {
283
+ [Key in keyof TFormats]: TFormats[Key] extends keyof I18nextFormatMap ? I18nextFormatMap[TFormats[Key]]['type'] : TFormats[Key] extends {} ? Expand<ReplaceOptionsFromFormats<TFormats[Key]>> : string;
284
+ };
285
+ /**
286
+ * Generates the formatParams options structure
287
+ *
288
+ * @ignore
289
+ */
290
+ type ReplaceFormatParamsFromFormats<TFormats extends {}> = {
291
+ [Key in keyof TFormats]?: TFormats[Key] extends keyof I18nextFormatMap ? I18nextFormatMap[TFormats[Key]]['options'] : TFormats[Key] extends {} ? Expand<ReplaceFormatParamsFromFormats<TFormats[Key]>> : undefined;
292
+ };
293
+ /**
294
+ * Extracts all nesting keys from a message string.
295
+ *
296
+ * @example
297
+ * ```
298
+ * 'foo $t(bar) $t(baz)' -> 'bar' | 'baz'
299
+ * ```
300
+ *
301
+ * @ignore
302
+ */
303
+ type NestingKeysFromMessage<TMessage extends string> = TMessage extends `${string}$t(${infer Key})${infer Tail}` ? Trim<Key> | NestingKeysFromMessage<Tail> : never;
304
+ /**
305
+ * Find all referenced keys, given a starting key and the full set of messages.
306
+ *
307
+ * This will only discover keys up to 3 levels deep.
308
+ *
309
+ * @example
310
+ * ```
311
+ * <'x', { x: '$t(y) $t(z)', y: 'y', z: '$t(w)', w: 'w', foo: 'foo' }> -> 'x' | 'y' | 'z' | 'w'
312
+ * ```
313
+ *
314
+ * @ignore
315
+ */
316
+ type NestedMessageKeys<TKey extends keyof TMessages, TMessages extends {
317
+ [key in string]: string;
318
+ }> = TKey | NestedMessageKeys2<NestingKeysFromMessage<TMessages[TKey]>, TMessages>;
319
+ type NestedMessageKeys2<TKey extends keyof TMessages, TMessages extends {
320
+ [key in string]: string;
321
+ }> = TKey | NestedMessageKeys3<NestingKeysFromMessage<TMessages[TKey]>, TMessages>;
322
+ type NestedMessageKeys3<TKey extends keyof TMessages, TMessages extends {
323
+ [key in string]: string;
324
+ }> = TKey | NestingKeysFromMessage<TMessages[TKey]>;
325
+ /**
326
+ * Converts a union type to an intersection type.
327
+ *
328
+ * @example
329
+ * ```
330
+ * { foo: 'foo' } | { bar: 'bar' } -> { foo: 'foo' } & { bar: 'bar' }
331
+ * ```
332
+ *
333
+ * @ignore
334
+ */
335
+ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
336
+ /**
337
+ * Collects different types of options into a single object
338
+ *
339
+ * @ignore
340
+ */
341
+ type CollectOptions<TCount extends {
342
+ count?: number;
343
+ }, TFormats extends {}> = TCount & (keyof Omit<TFormats, 'count'> extends never ? {} : (Expand<Omit<ReplaceOptionsFromFormats<TFormats>, 'count'>> | {
344
+ replace: Expand<Omit<ReplaceOptionsFromFormats<TFormats>, 'count'>>;
345
+ }) & {
346
+ formatParams?: Expand<ReplaceFormatParamsFromFormats<TFormats>>;
347
+ });
348
+ /**
349
+ * Helper type to only require options argument if needed
350
+ *
351
+ * @ignore
352
+ */
353
+ type OptionArgs<TOptions extends {}> = keyof TOptions extends never ? [options?: BaseOptions] : [options: BaseOptions & TOptions];
354
+ /**
355
+ * @ignore
356
+ */
357
+ type TranslationFunctionOptions<TKeys extends keyof TMessages, // All normalized message keys to be considered, i.e. included nested ones
358
+ TPluralKeys extends keyof TMessages, // All keys in the message map that are pluralized
359
+ TMessages extends {
360
+ [key in string]: string;
361
+ }> = OptionArgs<Expand<CollectOptions<TKeys & TPluralKeys extends never ? {} : {
362
+ count: number;
363
+ }, ExpandRecursive<UnionToIntersection<ReplaceFormatsFromMessage<TMessages[TKeys]>>>>>>;
364
+ /** @alpha */
365
+ interface TranslationFunction<TMessages extends {
366
+ [key in string]: string;
367
+ }> {
368
+ <TKey extends keyof CollapsedMessages<TMessages>>(key: TKey, ...[args]: TranslationFunctionOptions<NestedMessageKeys<TKey, CollapsedMessages<TMessages>>, PluralKeys<TMessages>, CollapsedMessages<TMessages>>): CollapsedMessages<TMessages>[TKey];
369
+ }
65
370
  /** @alpha */
66
- declare const useTranslationRef: <Messages extends Record<keyof Messages, string>>(translationRef: TranslationRef<Messages>) => <Tkey extends keyof Messages>(key: Tkey, options?: TranslationOptions) => Messages[Tkey];
371
+ type TranslationSnapshot<TMessages extends {
372
+ [key in string]: string;
373
+ }> = {
374
+ ready: false;
375
+ } | {
376
+ ready: true;
377
+ t: TranslationFunction<TMessages>;
378
+ };
379
+ /** @alpha */
380
+ type TranslationApi = {
381
+ getTranslation<TMessages extends {
382
+ [key in string]: string;
383
+ }>(translationRef: TranslationRef<string, TMessages>): TranslationSnapshot<TMessages>;
384
+ translation$<TMessages extends {
385
+ [key in string]: string;
386
+ }>(translationRef: TranslationRef<string, TMessages>): Observable<TranslationSnapshot<TMessages>>;
387
+ };
388
+ /**
389
+ * @alpha
390
+ */
391
+ declare const translationApiRef: ApiRef<TranslationApi>;
67
392
 
68
393
  /** @alpha */
69
- type AppTranslationApi = {
70
- getI18n(): i18n;
71
- addResourcesByRef<Messages extends Record<string, string>>(translationRef: TranslationRef<Messages>): void;
394
+ type AppLanguageApi = {
395
+ getAvailableLanguages(): {
396
+ languages: string[];
397
+ };
398
+ setLanguage(language?: string): void;
399
+ getLanguage(): {
400
+ language: string;
401
+ };
402
+ language$(): Observable<{
403
+ language: string;
404
+ }>;
72
405
  };
73
406
  /**
74
407
  * @alpha
75
408
  */
76
- declare const appTranslationApiRef: ApiRef<AppTranslationApi>;
409
+ declare const appLanguageApiRef: ApiRef<AppLanguageApi>;
410
+
411
+ /** @alpha */
412
+ declare const useTranslationRef: <TMessages extends {
413
+ [x: string]: string;
414
+ }>(translationRef: TranslationRef<string, TMessages>) => {
415
+ t: TranslationFunction<TMessages>;
416
+ };
77
417
 
78
- export { AppTranslationApi, PluginOptionsProviderProps, PluginProvider, TranslationOptions, TranslationRef, TranslationRefConfig, TranslationRefImpl, appTranslationApiRef, createTranslationRef, usePluginOptions, useTranslationRef };
418
+ export { AppLanguageApi, PluginOptionsProviderProps, PluginProvider, TranslationApi, TranslationFunction, TranslationMessages, TranslationMessagesOptions, TranslationRef, TranslationRefOptions, TranslationResource, TranslationResourceOptions, TranslationSnapshot, appLanguageApiRef, createTranslationMessages, createTranslationRef, createTranslationResource, translationApiRef, usePluginOptions, useTranslationRef };
package/dist/alpha.esm.js CHANGED
@@ -1,46 +1,179 @@
1
- import { u as useApi } from './esm/usePluginOptions-6dc02fab.esm.js';
1
+ import { u as useApi, r as errorApiRef } from './esm/usePluginOptions-6dc02fab.esm.js';
2
2
  export { P as PluginProvider, y as usePluginOptions } from './esm/usePluginOptions-6dc02fab.esm.js';
3
- import { useTranslation } from 'react-i18next';
3
+ import { useState, useMemo, useCallback, useEffect, useRef } from 'react';
4
4
  import { createApiRef } from '@backstage/core-plugin-api';
5
- import 'react';
6
5
  import '@backstage/version-bridge';
7
6
 
7
+ function createTranslationMessages(options) {
8
+ return {
9
+ $$type: "@backstage/TranslationMessages",
10
+ id: options.ref.id,
11
+ full: Boolean(options.full),
12
+ messages: options.messages
13
+ };
14
+ }
15
+
16
+ function createTranslationResource(options) {
17
+ return {
18
+ $$type: "@backstage/TranslationResource",
19
+ version: "v1",
20
+ id: options.ref.id,
21
+ resources: Object.entries(options.translations).map(
22
+ ([language, loader]) => ({
23
+ language,
24
+ loader: () => loader().then((m) => {
25
+ const value = m.default;
26
+ return {
27
+ messages: (value == null ? void 0 : value.$$type) === "@backstage/TranslationMessages" ? value.messages : value
28
+ };
29
+ })
30
+ })
31
+ )
32
+ };
33
+ }
34
+
35
+ var __defProp = Object.defineProperty;
36
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
37
+ var __publicField = (obj, key, value) => {
38
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
39
+ return value;
40
+ };
41
+ var __accessCheck = (obj, member, msg) => {
42
+ if (!member.has(obj))
43
+ throw TypeError("Cannot " + msg);
44
+ };
45
+ var __privateGet = (obj, member, getter) => {
46
+ __accessCheck(obj, member, "read from private field");
47
+ return getter ? getter.call(obj) : member.get(obj);
48
+ };
49
+ var __privateAdd = (obj, member, value) => {
50
+ if (member.has(obj))
51
+ throw TypeError("Cannot add the same private member more than once");
52
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
53
+ };
54
+ var __privateSet = (obj, member, value, setter) => {
55
+ __accessCheck(obj, member, "write to private field");
56
+ setter ? setter.call(obj, value) : member.set(obj, value);
57
+ return value;
58
+ };
59
+ var _id, _messages, _resources;
8
60
  class TranslationRefImpl {
9
- constructor(config) {
10
- this.config = config;
61
+ constructor(options) {
62
+ __privateAdd(this, _id, void 0);
63
+ __privateAdd(this, _messages, void 0);
64
+ __privateAdd(this, _resources, void 0);
65
+ __publicField(this, "$$type", "@backstage/TranslationRef");
66
+ __publicField(this, "version", "v1");
67
+ __privateSet(this, _id, options.id);
68
+ __privateSet(this, _messages, options.messages);
11
69
  }
12
- static create(config) {
13
- return new TranslationRefImpl(config);
70
+ get id() {
71
+ return __privateGet(this, _id);
14
72
  }
15
- getId() {
16
- return this.config.id;
73
+ get T() {
74
+ throw new Error("Not implemented");
17
75
  }
18
76
  getDefaultMessages() {
19
- return this.config.messages;
77
+ return __privateGet(this, _messages);
20
78
  }
21
- getLazyResources() {
22
- return this.config.lazyResources;
79
+ setDefaultResource(resources) {
80
+ __privateSet(this, _resources, resources);
23
81
  }
24
- getResources() {
25
- return this.config.resources;
82
+ getDefaultResource() {
83
+ return __privateGet(this, _resources);
26
84
  }
27
85
  toString() {
28
- return `TranslationRef(${this.getId()})`;
86
+ return `TranslationRef{id=${this.id}}`;
87
+ }
88
+ }
89
+ _id = new WeakMap();
90
+ _messages = new WeakMap();
91
+ _resources = new WeakMap();
92
+ function createTranslationRef(config) {
93
+ const ref = new TranslationRefImpl(config);
94
+ if (config.translations) {
95
+ ref.setDefaultResource(
96
+ createTranslationResource({
97
+ ref,
98
+ translations: config.translations
99
+ })
100
+ );
29
101
  }
102
+ return ref;
30
103
  }
31
- const createTranslationRef = (config) => TranslationRefImpl.create(config);
32
104
 
33
- const appTranslationApiRef = createApiRef({
34
- id: "core.apptranslation"
105
+ const translationApiRef = createApiRef({
106
+ id: "core.translation"
35
107
  });
36
108
 
109
+ const appLanguageApiRef = createApiRef({
110
+ id: "core.applanguage"
111
+ });
112
+
113
+ const loggedRefs = /* @__PURE__ */ new WeakSet();
37
114
  const useTranslationRef = (translationRef) => {
38
- const appTranslationApi = useApi(appTranslationApiRef);
39
- appTranslationApi.addResourcesByRef(translationRef);
40
- const { t } = useTranslation(translationRef.getId());
41
- const defaulteMessage = translationRef.getDefaultMessages();
42
- return (key, options) => t(key, defaulteMessage[key], options);
115
+ const errorApi = useApi(errorApiRef);
116
+ const translationApi = useApi(translationApiRef);
117
+ const [snapshot, setSnapshot] = useState(
118
+ () => translationApi.getTranslation(translationRef)
119
+ );
120
+ const observable = useMemo(
121
+ () => translationApi.translation$(translationRef),
122
+ [translationApi, translationRef]
123
+ );
124
+ const onError = useCallback(
125
+ (error) => {
126
+ if (!loggedRefs.has(translationRef)) {
127
+ const errMsg = `Failed to load translation resource '${translationRef.id}'; caused by ${error}`;
128
+ console.error(errMsg);
129
+ errorApi.post(new Error(errMsg));
130
+ loggedRefs.add(translationRef);
131
+ }
132
+ },
133
+ [errorApi, translationRef]
134
+ );
135
+ useEffect(() => {
136
+ const subscription = observable.subscribe({
137
+ next(next) {
138
+ if (next.ready) {
139
+ setSnapshot(next);
140
+ }
141
+ },
142
+ error(error) {
143
+ onError(error);
144
+ }
145
+ });
146
+ return () => {
147
+ subscription.unsubscribe();
148
+ };
149
+ }, [observable, onError]);
150
+ const initialRenderRef = useRef(true);
151
+ useEffect(() => {
152
+ if (initialRenderRef.current) {
153
+ initialRenderRef.current = false;
154
+ } else {
155
+ setSnapshot(translationApi.getTranslation(translationRef));
156
+ }
157
+ }, [translationApi, translationRef]);
158
+ if (!snapshot.ready) {
159
+ throw new Promise((resolve) => {
160
+ const subscription = observable.subscribe({
161
+ next(next) {
162
+ if (next.ready) {
163
+ subscription.unsubscribe();
164
+ resolve();
165
+ }
166
+ },
167
+ error(error) {
168
+ subscription.unsubscribe();
169
+ onError(error);
170
+ resolve();
171
+ }
172
+ });
173
+ });
174
+ }
175
+ return { t: snapshot.t };
43
176
  };
44
177
 
45
- export { TranslationRefImpl, appTranslationApiRef, createTranslationRef, useTranslationRef };
178
+ export { appLanguageApiRef, createTranslationMessages, createTranslationRef, createTranslationResource, translationApiRef, useTranslationRef };
46
179
  //# sourceMappingURL=alpha.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"alpha.esm.js","sources":["../src/translation/TranslationRef.ts","../src/apis/definitions/AppTranslationApi.ts","../src/translation/useTranslationRef.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 { TranslationRef, TranslationRefConfig } from './types';\n\n/** @alpha */\nexport class TranslationRefImpl<Messages extends Record<keyof Messages, string>>\n implements TranslationRef<Messages>\n{\n static create<Messages extends Record<keyof Messages, string>>(\n config: TranslationRefConfig<Messages>,\n ) {\n return new TranslationRefImpl(config);\n }\n\n getId() {\n return this.config.id;\n }\n\n getDefaultMessages(): Messages {\n return this.config.messages;\n }\n\n getLazyResources():\n | Record<string, () => Promise<{ messages: Messages }>>\n | undefined {\n return this.config.lazyResources;\n }\n\n getResources(): Record<string, Messages> | undefined {\n return this.config.resources;\n }\n\n toString() {\n return `TranslationRef(${this.getId()})`;\n }\n\n private constructor(\n private readonly config: TranslationRefConfig<Messages>,\n ) {}\n}\n\n/** @alpha */\nexport const createTranslationRef = <\n Messages extends Record<keyof Messages, string> = {},\n>(\n config: TranslationRefConfig<Messages>,\n): TranslationRef<Messages> => TranslationRefImpl.create(config);\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 { type i18n } from 'i18next';\nimport { TranslationRef } from '../../translation';\nimport { ApiRef, createApiRef } from '@backstage/core-plugin-api';\n\n/** @alpha */\nexport type AppTranslationApi = {\n getI18n(): i18n;\n\n addResourcesByRef<Messages extends Record<string, string>>(\n translationRef: TranslationRef<Messages>,\n ): void;\n};\n\n/**\n * @alpha\n */\nexport const appTranslationApiRef: ApiRef<AppTranslationApi> = createApiRef({\n id: 'core.apptranslation',\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 { useTranslation } from 'react-i18next';\n\nimport { TranslationOptions, TranslationRef } from './types';\nimport { useApi } from '../apis';\nimport { appTranslationApiRef } from '../apis/alpha';\n\n/** @alpha */\nexport const useTranslationRef = <\n Messages extends Record<keyof Messages, string>,\n>(\n translationRef: TranslationRef<Messages>,\n) => {\n const appTranslationApi = useApi(appTranslationApiRef);\n\n appTranslationApi.addResourcesByRef(translationRef);\n\n const { t } = useTranslation(translationRef.getId());\n\n const defaulteMessage = translationRef.getDefaultMessages();\n\n return <Tkey extends keyof Messages>(\n key: Tkey,\n options?: TranslationOptions,\n ): Messages[Tkey] => t(key as string, defaulteMessage[key], options);\n};\n"],"names":[],"mappings":";;;;;;;AAmBO,MAAM,kBAEb,CAAA;AAAA,EA6BU,YACW,MACjB,EAAA;AADiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AAAA,GAChB;AAAA,EA9BH,OAAO,OACL,MACA,EAAA;AACA,IAAO,OAAA,IAAI,mBAAmB,MAAM,CAAA,CAAA;AAAA,GACtC;AAAA,EAEA,KAAQ,GAAA;AACN,IAAA,OAAO,KAAK,MAAO,CAAA,EAAA,CAAA;AAAA,GACrB;AAAA,EAEA,kBAA+B,GAAA;AAC7B,IAAA,OAAO,KAAK,MAAO,CAAA,QAAA,CAAA;AAAA,GACrB;AAAA,EAEA,gBAEc,GAAA;AACZ,IAAA,OAAO,KAAK,MAAO,CAAA,aAAA,CAAA;AAAA,GACrB;AAAA,EAEA,YAAqD,GAAA;AACnD,IAAA,OAAO,KAAK,MAAO,CAAA,SAAA,CAAA;AAAA,GACrB;AAAA,EAEA,QAAW,GAAA;AACT,IAAO,OAAA,CAAA,eAAA,EAAkB,IAAK,CAAA,KAAA,EAAO,CAAA,CAAA,CAAA,CAAA;AAAA,GACvC;AAKF,CAAA;AAGO,MAAM,oBAAuB,GAAA,CAGlC,MAC6B,KAAA,kBAAA,CAAmB,OAAO,MAAM;;AC5BxD,MAAM,uBAAkD,YAAa,CAAA;AAAA,EAC1E,EAAI,EAAA,qBAAA;AACN,CAAC;;ACXY,MAAA,iBAAA,GAAoB,CAG/B,cACG,KAAA;AACH,EAAM,MAAA,iBAAA,GAAoB,OAAO,oBAAoB,CAAA,CAAA;AAErD,EAAA,iBAAA,CAAkB,kBAAkB,cAAc,CAAA,CAAA;AAElD,EAAA,MAAM,EAAE,CAAE,EAAA,GAAI,cAAe,CAAA,cAAA,CAAe,OAAO,CAAA,CAAA;AAEnD,EAAM,MAAA,eAAA,GAAkB,eAAe,kBAAmB,EAAA,CAAA;AAE1D,EAAO,OAAA,CACL,KACA,OACmB,KAAA,CAAA,CAAE,KAAe,eAAgB,CAAA,GAAG,GAAG,OAAO,CAAA,CAAA;AACrE;;;;"}
1
+ {"version":3,"file":"alpha.esm.js","sources":["../src/translation/TranslationMessages.ts","../src/translation/TranslationResource.ts","../src/translation/TranslationRef.ts","../src/apis/definitions/TranslationApi.ts","../src/apis/definitions/AppLanguageApi.ts","../src/translation/useTranslationRef.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 { TranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/**\n * Represents a collection of messages to be provided for a given translation ref.\n *\n * @alpha\n * @remarks\n *\n * This collection of messages can either be used directly as an override for the\n * default messages, or it can be used to provide translations for a language by\n * by being referenced by a {@link TranslationResource}.\n */\nexport interface TranslationMessages<\n TId extends string = string,\n TMessages extends { [key in string]: string } = { [key in string]: string },\n TFull extends boolean = boolean,\n> {\n $$type: '@backstage/TranslationMessages';\n /** The ID of the translation ref that these messages are for */\n id: TId;\n /** Whether or not these messages override all known messages */\n full: TFull;\n /** The messages provided for the given translation ref */\n messages: TMessages;\n}\n\n/**\n * Options for {@link createTranslationMessages}.\n *\n * @alpha\n */\nexport interface TranslationMessagesOptions<\n TId extends string,\n TMessages extends { [key in string]: string },\n TFull extends boolean,\n> {\n ref: TranslationRef<TId, TMessages>;\n\n full?: TFull;\n\n messages: false extends TFull\n ? { [key in keyof TMessages]?: string | null }\n : { [key in keyof TMessages]: string | null };\n}\n\n/**\n * Creates a collection of messages for a given translation ref.\n *\n * @alpha\n */\nexport function createTranslationMessages<\n TId extends string,\n TMessages extends { [key in string]: string },\n TFull extends boolean,\n>(\n options: TranslationMessagesOptions<TId, TMessages, TFull>,\n): TranslationMessages<TId, TMessages, TFull> {\n return {\n $$type: '@backstage/TranslationMessages',\n id: options.ref.id,\n full: Boolean(options.full) as TFull,\n messages: options.messages as TMessages,\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 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 {\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/** @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 TMessages extends { [key in string]: string },\n TTranslations extends {\n [language in string]: () => Promise<{\n default: { [key in keyof TMessages]: string | null };\n }>;\n },\n> {\n id: TId;\n messages: TMessages;\n translations?: TTranslations;\n}\n\n/** @internal */\nclass TranslationRefImpl<\n TId extends string,\n TMessages extends { [key in string]: string },\n> implements InternalTranslationRef<TId, TMessages>\n{\n #id: TId;\n #messages: TMessages;\n #resources: TranslationResource | undefined;\n\n constructor(options: TranslationRefOptions<TId, TMessages, any>) {\n this.#id = options.id;\n this.#messages = options.messages;\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 TMessages extends { [key in string]: string },\n TTranslations extends {\n [language in string]: () => Promise<{\n default: { [key in keyof TMessages]: string | null };\n }>;\n },\n>(\n config: TranslationRefOptions<TId, TMessages, TTranslations>,\n): TranslationRef<TId, TMessages> {\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 { [key in string]: string },\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 { ApiRef, createApiRef } from '@backstage/core-plugin-api';\nimport { Observable } from '@backstage/types';\nimport { TranslationRef } from '../../translation';\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 * Helper type that expands type hints\n *\n * @ignore\n */\ntype Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;\n\n/**\n * Helper type that expands type hints recursively\n *\n * @ignore\n */\ntype ExpandRecursive<T> = T extends infer O\n ? { [K in keyof O]: ExpandRecursive<O[K]> }\n : never;\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 {}> = {\n [Key in keyof TFormats]: TFormats[Key] extends keyof I18nextFormatMap\n ? I18nextFormatMap[TFormats[Key]]['type']\n : TFormats[Key] extends {}\n ? Expand<ReplaceOptionsFromFormats<TFormats[Key]>>\n : string;\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> = TCount &\n // count is special, omit it from the replacements\n (keyof Omit<TFormats, 'count'> extends never\n ? {}\n : (\n | Expand<Omit<ReplaceOptionsFromFormats<TFormats>, 'count'>>\n | {\n replace: Expand<Omit<ReplaceOptionsFromFormats<TFormats>, 'count'>>;\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?: BaseOptions]\n : [options: 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> = OptionArgs<\n Expand<\n CollectOptions<\n TKeys & TPluralKeys extends never ? {} : { count: number },\n ExpandRecursive<\n UnionToIntersection<ReplaceFormatsFromMessage<TMessages[TKeys]>>\n >\n >\n >\n>;\n\n/** @alpha */\nexport interface TranslationFunction<\n TMessages extends { [key in string]: string },\n> {\n <TKey extends keyof CollapsedMessages<TMessages>>(\n key: TKey,\n ...[args]: TranslationFunctionOptions<\n NestedMessageKeys<TKey, CollapsedMessages<TMessages>>,\n PluralKeys<TMessages>,\n CollapsedMessages<TMessages>\n >\n ): CollapsedMessages<TMessages>[TKey];\n}\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 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 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"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/analytics/AnalyticsContext.tsx","../src/apis/system/helpers.ts","../src/analytics/Tracker.ts","../src/analytics/useAnalytics.tsx","../src/app/useApp.tsx","../src/extensions/componentData.tsx","../src/routing/types.ts","../src/routing/RouteRef.ts","../src/routing/SubRouteRef.ts","../src/routing/ExternalRouteRef.ts","../src/routing/useRouteRef.tsx","../src/routing/useRouteRefParams.ts","../src/extensions/PluginErrorBoundary.tsx","../src/extensions/extensions.tsx","../src/extensions/useElementFilter.tsx","../src/plugin/Plugin.tsx"],"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 {\n createVersionedContext,\n createVersionedValueMap,\n} from '@backstage/version-bridge';\nimport React, { 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: React.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 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 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 './';\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 { 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 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 AnyParams = { [param in string]: string } | undefined;\n\n/**\n * Type describing the key type of a route parameter mapping.\n *\n * @public\n */\nexport type ParamKeys<Params extends AnyParams> = keyof Params extends never\n ? []\n : (keyof Params)[];\n\n/**\n * Optional route params.\n *\n * @public\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 $$routeRefType: 'absolute'; // See routeRefType above\n\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 $$routeRefType: 'sub'; // See routeRefType above\n\n parent: RouteRef;\n\n path: string;\n\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 $$routeRefType: 'external'; // See routeRefType above\n\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 {\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 {\n AnyParams,\n OptionalParams,\n ParamKeys,\n RouteRef,\n routeRefType,\n SubRouteRef,\n} from './types';\n\n// Should match the pattern in react-router\nconst PARAM_PATTERN = /^\\w+$/;\n\n/**\n * @internal\n */\nexport class SubRouteRefImpl<Params extends AnyParams>\n implements SubRouteRef<Params>\n{\n // The marker is used for type checking while the symbol is used at runtime.\n declare $$routeRefType: 'sub';\n readonly [routeRefType] = 'sub';\n\n constructor(\n private readonly id: string,\n readonly path: string,\n readonly parent: RouteRef,\n readonly params: ParamKeys<Params>,\n ) {}\n\n toString() {\n return `routeRef{type=sub,id=${this.id}}`;\n }\n}\n\n/**\n * Used in {@link PathParams} type declaration.\n * @public\n */\nexport type ParamPart<S extends string> = S extends `:${infer Param}`\n ? Param\n : never;\n\n/**\n * Used in {@link PathParams} type declaration.\n * @public\n */\nexport type ParamNames<S extends string> =\n S extends `${infer Part}/${infer Rest}`\n ? ParamPart<Part> | ParamNames<Rest>\n : ParamPart<S>;\n/**\n * This utility type helps us infer a Param object type from a string path\n * For example, `/foo/:bar/:baz` inferred to `{ bar: string, baz: string }`\n * @public\n */\nexport type PathParams<S extends string> = { [name in ParamNames<S>]: string };\n\n/**\n * Merges a param object type with an optional params type into a params object.\n * @public\n */\nexport type MergeParams<\n P1 extends { [param in string]: string },\n P2 extends AnyParams,\n> = (P1[keyof P1] extends never ? {} : P1) & (P2 extends undefined ? {} : P2);\n\n/**\n * Creates a SubRouteRef type given the desired parameters and parent route parameters.\n * The parameters types are merged together while ensuring that there is no overlap between the two.\n *\n * @public\n */\nexport type MakeSubRouteRef<\n Params extends { [param in string]: string },\n ParentParams extends AnyParams,\n> = keyof Params & keyof ParentParams extends never\n ? SubRouteRef<OptionalParams<MergeParams<Params, ParentParams>>>\n : never;\n\n/**\n * Create a {@link SubRouteRef} from a route descriptor.\n *\n * @param config - Description of the route reference to be created.\n * @public\n */\nexport function createSubRouteRef<\n Path extends string,\n ParentParams extends AnyParams = never,\n>(config: {\n id: string;\n path: Path;\n parent: RouteRef<ParentParams>;\n}): MakeSubRouteRef<PathParams<Path>, ParentParams> {\n const { id, path, parent } = config;\n type Params = PathParams<Path>;\n\n // Collect runtime parameters from the path, e.g. ['bar', 'baz'] from '/foo/:bar/:baz'\n const pathParams = path\n .split('/')\n .filter(p => p.startsWith(':'))\n .map(p => p.substring(1));\n const params = [...parent.params, ...pathParams];\n\n if (parent.params.some(p => pathParams.includes(p as string))) {\n throw new Error(\n 'SubRouteRef may not have params that overlap with its parent',\n );\n }\n if (!path.startsWith('/')) {\n throw new Error(`SubRouteRef path must start with '/', got '${path}'`);\n }\n if (path.endsWith('/')) {\n throw new Error(`SubRouteRef path must not end with '/', got '${path}'`);\n }\n for (const param of pathParams) {\n if (!PARAM_PATTERN.test(param)) {\n throw new Error(`SubRouteRef path has invalid param, got '${param}'`);\n }\n }\n\n // We ensure that the type of the return type is sane here\n const subRouteRef = new SubRouteRefImpl(\n id,\n path,\n parent,\n params as ParamKeys<MergeParams<Params, ParentParams>>,\n ) as SubRouteRef<OptionalParams<MergeParams<Params, ParentParams>>>;\n\n // But skip type checking of the return value itself, because the conditional\n // type checking of the parent parameter overlap is tricky to express.\n return subRouteRef as any;\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 ) {}\n\n toString() {\n return `routeRef{type=external,id=${this.id}}`;\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}): 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 );\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 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 { useParams } from 'react-router-dom';\nimport { RouteRef, AnyParams, SubRouteRef } from './types';\n\n/**\n * React hook for retrieving dynamic params from the current URL.\n * @param _routeRef - Ref of the current route.\n * @public\n */\nexport function useRouteRefParams<Params extends AnyParams>(\n _routeRef: RouteRef<Params> | SubRouteRef<Params>,\n): Params {\n return useParams() as Params;\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 React from 'react';\nimport { AppContext } from '../app/types';\nimport { BackstagePlugin } from '../plugin';\n\ntype Props = {\n app: AppContext;\n plugin: BackstagePlugin;\n};\n\ntype State = { error: Error | undefined };\n\nexport class PluginErrorBoundary extends React.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 React, { 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 { PluginProvider } from '../plugin-options';\nimport { routableExtensionRenderedEvent } from '../analytics/Tracker';\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(\n 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 error => {\n const RoutableExtensionWrapper: any = (_: any) => {\n const app = useApp();\n const { BootErrorPage } = app.getComponents();\n\n return <BootErrorPage step=\"load-chunk\" error={error} />;\n };\n return RoutableExtensionWrapper;\n },\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(component => ({ default: component })),\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 <PluginProvider plugin={plugin}>\n <Component {...props} />\n </PluginProvider>\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 PluginInputOptions extends {},\n> implements BackstagePlugin<Routes, ExternalRoutes, PluginInputOptions>\n{\n constructor(\n private readonly config: PluginConfig<\n Routes,\n ExternalRoutes,\n PluginInputOptions\n >,\n ) {}\n\n private options: {} | undefined = undefined;\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 __experimentalReconfigure(options: PluginInputOptions): void {\n if (this.config.__experimentalConfigure) {\n this.options = this.config.__experimentalConfigure(options);\n }\n }\n\n getPluginOptions(): {} {\n if (this.config.__experimentalConfigure && !this.options) {\n this.options = this.config.__experimentalConfigure();\n }\n return this.options ?? {};\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 PluginInputOptions extends {} = {},\n>(\n config: PluginConfig<Routes, ExternalRoutes, PluginInputOptions>,\n): BackstagePlugin<Routes, ExternalRoutes, PluginInputOptions> {\n return new PluginImpl(config);\n}\n"],"names":["_a","__publicField"],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/analytics/AnalyticsContext.tsx","../src/apis/system/helpers.ts","../src/analytics/Tracker.ts","../src/analytics/useAnalytics.tsx","../src/app/useApp.tsx","../src/extensions/componentData.tsx","../src/routing/types.ts","../src/routing/RouteRef.ts","../src/routing/SubRouteRef.ts","../src/routing/ExternalRouteRef.ts","../src/routing/useRouteRef.tsx","../src/routing/useRouteRefParams.ts","../src/extensions/PluginErrorBoundary.tsx","../src/extensions/extensions.tsx","../src/extensions/useElementFilter.tsx","../src/plugin/Plugin.tsx"],"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 {\n createVersionedContext,\n createVersionedValueMap,\n} from '@backstage/version-bridge';\nimport React, { 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: React.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 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 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 './';\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 { 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 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 AnyParams = { [param in string]: string } | undefined;\n\n/**\n * Type describing the key type of a route parameter mapping.\n *\n * @public\n */\nexport type ParamKeys<Params extends AnyParams> = keyof Params extends never\n ? []\n : (keyof Params)[];\n\n/**\n * Optional route params.\n *\n * @public\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 $$routeRefType: 'absolute'; // See routeRefType above\n\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 $$routeRefType: 'sub'; // See routeRefType above\n\n parent: RouteRef;\n\n path: string;\n\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 $$routeRefType: 'external'; // See routeRefType above\n\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 {\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 {\n AnyParams,\n OptionalParams,\n ParamKeys,\n RouteRef,\n routeRefType,\n SubRouteRef,\n} from './types';\n\n// Should match the pattern in react-router\nconst PARAM_PATTERN = /^\\w+$/;\n\n/**\n * @internal\n */\nexport class SubRouteRefImpl<Params extends AnyParams>\n implements SubRouteRef<Params>\n{\n // The marker is used for type checking while the symbol is used at runtime.\n declare $$routeRefType: 'sub';\n readonly [routeRefType] = 'sub';\n\n constructor(\n private readonly id: string,\n readonly path: string,\n readonly parent: RouteRef,\n readonly params: ParamKeys<Params>,\n ) {}\n\n toString() {\n return `routeRef{type=sub,id=${this.id}}`;\n }\n}\n\n/**\n * Used in {@link PathParams} type declaration.\n * @public\n */\nexport type ParamPart<S extends string> = S extends `:${infer Param}`\n ? Param\n : never;\n\n/**\n * Used in {@link PathParams} type declaration.\n * @public\n */\nexport type ParamNames<S extends string> =\n S extends `${infer Part}/${infer Rest}`\n ? ParamPart<Part> | ParamNames<Rest>\n : ParamPart<S>;\n/**\n * This utility type helps us infer a Param object type from a string path\n * For example, `/foo/:bar/:baz` inferred to `{ bar: string, baz: string }`\n * @public\n */\nexport type PathParams<S extends string> = { [name in ParamNames<S>]: string };\n\n/**\n * Merges a param object type with an optional params type into a params object.\n * @public\n */\nexport type MergeParams<\n P1 extends { [param in string]: string },\n P2 extends AnyParams,\n> = (P1[keyof P1] extends never ? {} : P1) & (P2 extends undefined ? {} : P2);\n\n/**\n * Creates a SubRouteRef type given the desired parameters and parent route parameters.\n * The parameters types are merged together while ensuring that there is no overlap between the two.\n *\n * @public\n */\nexport type MakeSubRouteRef<\n Params extends { [param in string]: string },\n ParentParams extends AnyParams,\n> = keyof Params & keyof ParentParams extends never\n ? SubRouteRef<OptionalParams<MergeParams<Params, ParentParams>>>\n : never;\n\n/**\n * Create a {@link SubRouteRef} from a route descriptor.\n *\n * @param config - Description of the route reference to be created.\n * @public\n */\nexport function createSubRouteRef<\n Path extends string,\n ParentParams extends AnyParams = never,\n>(config: {\n id: string;\n path: Path;\n parent: RouteRef<ParentParams>;\n}): MakeSubRouteRef<PathParams<Path>, ParentParams> {\n const { id, path, parent } = config;\n type Params = PathParams<Path>;\n\n // Collect runtime parameters from the path, e.g. ['bar', 'baz'] from '/foo/:bar/:baz'\n const pathParams = path\n .split('/')\n .filter(p => p.startsWith(':'))\n .map(p => p.substring(1));\n const params = [...parent.params, ...pathParams];\n\n if (parent.params.some(p => pathParams.includes(p as string))) {\n throw new Error(\n 'SubRouteRef may not have params that overlap with its parent',\n );\n }\n if (!path.startsWith('/')) {\n throw new Error(`SubRouteRef path must start with '/', got '${path}'`);\n }\n if (path.endsWith('/')) {\n throw new Error(`SubRouteRef path must not end with '/', got '${path}'`);\n }\n for (const param of pathParams) {\n if (!PARAM_PATTERN.test(param)) {\n throw new Error(`SubRouteRef path has invalid param, got '${param}'`);\n }\n }\n\n // We ensure that the type of the return type is sane here\n const subRouteRef = new SubRouteRefImpl(\n id,\n path,\n parent,\n params as ParamKeys<MergeParams<Params, ParentParams>>,\n ) as SubRouteRef<OptionalParams<MergeParams<Params, ParentParams>>>;\n\n // But skip type checking of the return value itself, because the conditional\n // type checking of the parent parameter overlap is tricky to express.\n return subRouteRef as any;\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 ) {}\n\n toString() {\n return `routeRef{type=external,id=${this.id}}`;\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}): 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 );\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 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 { useParams } from 'react-router-dom';\nimport { RouteRef, AnyParams, SubRouteRef } from './types';\n\n/**\n * React hook for retrieving dynamic params from the current URL.\n * @param _routeRef - Ref of the current route.\n * @public\n */\nexport function useRouteRefParams<Params extends AnyParams>(\n _routeRef: RouteRef<Params> | SubRouteRef<Params>,\n): Params {\n return useParams() as Params;\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 React from 'react';\nimport { AppContext } from '../app/types';\nimport { BackstagePlugin } from '../plugin';\n\ntype Props = React.PropsWithChildren<{\n app: AppContext;\n plugin: BackstagePlugin;\n}>;\n\ntype State = { error: Error | undefined };\n\nexport class PluginErrorBoundary extends React.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 React, { 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 { PluginProvider } from '../plugin-options';\nimport { routableExtensionRenderedEvent } from '../analytics/Tracker';\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(\n 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 error => {\n const RoutableExtensionWrapper: any = (_: any) => {\n const app = useApp();\n const { BootErrorPage } = app.getComponents();\n\n return <BootErrorPage step=\"load-chunk\" error={error} />;\n };\n return RoutableExtensionWrapper;\n },\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(component => ({ default: component })),\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 <PluginProvider plugin={plugin}>\n <Component {...props} />\n </PluginProvider>\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 PluginInputOptions extends {},\n> implements BackstagePlugin<Routes, ExternalRoutes, PluginInputOptions>\n{\n constructor(\n private readonly config: PluginConfig<\n Routes,\n ExternalRoutes,\n PluginInputOptions\n >,\n ) {}\n\n private options: {} | undefined = undefined;\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 __experimentalReconfigure(options: PluginInputOptions): void {\n if (this.config.__experimentalConfigure) {\n this.options = this.config.__experimentalConfigure(options);\n }\n }\n\n getPluginOptions(): {} {\n if (this.config.__experimentalConfigure && !this.options) {\n this.options = this.config.__experimentalConfigure();\n }\n return this.options ?? {};\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 PluginInputOptions extends {} = {},\n>(\n config: PluginConfig<Routes, ExternalRoutes, PluginInputOptions>,\n): BackstagePlugin<Routes, ExternalRoutes, PluginInputOptions> {\n return new PluginImpl(config);\n}\n"],"names":["_a","__publicField"],"mappings":";;;;;;AAuBA,MAAM,qBAAA,GAAwB,uBAE3B,mBAAmB,CAAA,CAAA;AAQf,MAAM,sBAAsB,MAA6B;AAC9D,EAAM,MAAA,UAAA,GAAa,WAAW,qBAAqB,CAAA,CAAA;AAGnD,EAAA,IAAI,eAAe,KAAW,CAAA,EAAA;AAC5B,IAAO,OAAA;AAAA,MACL,QAAU,EAAA,SAAA;AAAA,MACV,QAAU,EAAA,MAAA;AAAA,MACV,SAAW,EAAA,KAAA;AAAA,KACb,CAAA;AAAA,GACF;AAGA,EAAM,MAAA,QAAA,GAAW,UAAW,CAAA,SAAA,CAAU,CAAC,CAAA,CAAA;AACvC,EAAA,IAAI,aAAa,KAAW,CAAA,EAAA;AAC1B,IAAM,MAAA,IAAI,MAAM,iCAAiC,CAAA,CAAA;AAAA,GACnD;AAEA,EAAO,OAAA,QAAA,CAAA;AACT,CAAA,CAAA;AAaa,MAAA,gBAAA,GAAmB,CAAC,OAG3B,KAAA;AACJ,EAAM,MAAA,EAAE,UAAY,EAAA,QAAA,EAAa,GAAA,OAAA,CAAA;AAEjC,EAAA,MAAM,eAAe,mBAAoB,EAAA,CAAA;AACzC,EAAA,MAAM,aAAgB,GAAA;AAAA,IACpB,GAAG,YAAA;AAAA,IACH,GAAG,UAAA;AAAA,GACL,CAAA;AAEA,EAAA,MAAM,sBAAyB,GAAA,uBAAA,CAAwB,EAAE,CAAA,EAAG,eAAe,CAAA,CAAA;AAC3E,EAAA,2CACG,qBAAsB,CAAA,QAAA,EAAtB,EAA+B,KAAA,EAAO,0BACpC,QACH,CAAA,CAAA;AAEJ;;AC1BgB,SAAA,gBAAA,CAKd,SACA,QAC6B,EAAA;AAC7B,EAAA,IAAI,QAAQ,OAAS,EAAA;AACnB,IAAO,OAAA;AAAA,MACL,GAAK,EAAA,OAAA;AAAA,MACL,MAAM,EAAC;AAAA,MACP,SAAS,MAAM,QAAA;AAAA,KACjB,CAAA;AAAA,GACF;AACA,EAAO,OAAA,OAAA,CAAA;AACT;;ACrBA,MAAM,YAAe,GAAA,0BAAA;AAAA,EACnB,0CAAA;AAAA,EACA,OAAO;AAAA,IACL,4BAA8B,EAAA,KAAA,CAAA;AAAA,IAC9B,iCAAmC,EAAA,KAAA,CAAA;AAAA,IACnC,sBAAwB,EAAA,KAAA;AAAA,GAC1B,CAAA;AACF,CAAA,CAAA;AAKO,MAAM,8BAAiC,GAAA,8BAAA,CAAA;AAEvC,MAAM,OAAoC,CAAA;AAAA,EAC/C,WAAA,CACmB,cACT,OAAiC,GAAA;AAAA,IACvC,QAAU,EAAA,SAAA;AAAA,IACV,QAAU,EAAA,MAAA;AAAA,IACV,SAAW,EAAA,KAAA;AAAA,GAEb,EAAA;AANiB,IAAA,IAAA,CAAA,YAAA,GAAA,YAAA,CAAA;AACT,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA,CAAA;AAOR,IAAI,IAAA,CAAC,aAAa,sBAAwB,EAAA;AAGxC,MAAA,gBAAA;AAAA,QACE,cAAA;AAAA,QACA,MAAM;AACJ,UAAA,IAAI,aAAa,4BAA8B,EAAA;AAC7C,YAAA,IAAA,CAAK,aAAa,YAAa,CAAA;AAAA,cAC7B,GAAG,YAAa,CAAA,4BAAA;AAAA,cAChB,GAAG,YAAa,CAAA,iCAAA;AAAA,aACjB,CAAA,CAAA;AACD,YAAA,YAAA,CAAa,4BAA+B,GAAA,KAAA,CAAA,CAAA;AAC5C,YAAA,YAAA,CAAa,iCAAoC,GAAA,KAAA,CAAA,CAAA;AAAA,WACnD;AAAA,SACF;AAAA,QACA,EAAE,IAAA,EAAM,IAAM,EAAA,OAAA,EAAS,IAAK,EAAA;AAAA,OAC9B,CAAA;AAGA,MAAA,YAAA,CAAa,sBAAyB,GAAA,IAAA,CAAA;AAAA,KACxC;AAAA,GACF;AAAA,EAEA,WAAW,OAAgC,EAAA;AACzC,IAAA,IAAA,CAAK,OAAU,GAAA,OAAA,CAAA;AAAA,GACjB;AAAA,EAEA,YAAA,CACE,QACA,OACA,EAAA;AAAA,IACE,KAAA;AAAA,IACA,UAAA;AAAA,GACF,GAA+D,EAC/D,EAAA;AAEA,IAAA,MAAM,EAAE,cAAA,EAAgB,GAAG,OAAA,KAAY,IAAK,CAAA,OAAA,CAAA;AAG5C,IAAA,IAAI,WAAW,8BAAgC,EAAA;AAG7C,MAAA,IAAI,aAAa,4BAA8B,EAAA;AAC7C,QAAA,YAAA,CAAa,iCAAoC,GAAA;AAAA,UAC/C,OAAS,EAAA;AAAA,YACP,GAAG,OAAA;AAAA,YACH,SAAW,EAAA,KAAA;AAAA,WACb;AAAA,SACF,CAAA;AAAA,OACF;AACA,MAAA,OAAA;AAAA,KACF;AAKA,IAAA,IAAI,aAAa,4BAA8B,EAAA;AAC7C,MAAI,IAAA;AACF,QAAA,IAAA,CAAK,aAAa,YAAa,CAAA;AAAA,UAC7B,GAAG,YAAa,CAAA,4BAAA;AAAA,UAChB,GAAG,YAAa,CAAA,iCAAA;AAAA,SACjB,CAAA,CAAA;AAAA,eACM,CAAG,EAAA;AAEV,QAAQ,OAAA,CAAA,IAAA,CAAK,4CAA4C,CAAC,CAAA,CAAA;AAAA,OAC5D;AAGA,MAAA,YAAA,CAAa,4BAA+B,GAAA,KAAA,CAAA,CAAA;AAC5C,MAAA,YAAA,CAAa,iCAAoC,GAAA,KAAA,CAAA,CAAA;AAAA,KACnD;AAIA,IAAA,IACE,WAAW,UACX,IAAA,cAAA,KAAmB,UACnB,IAAA,OAAA,CAAQ,aAAa,MACrB,EAAA;AAEA,MAAA,YAAA,CAAa,4BAA+B,GAAA;AAAA,QAC1C,MAAA;AAAA,QACA,OAAA;AAAA,QACA,KAAA;AAAA,QACA,UAAA;AAAA,QACA,OAAA;AAAA,OACF,CAAA;AACA,MAAA,OAAA;AAAA,KACF;AAEA,IAAI,IAAA;AACF,MAAA,IAAA,CAAK,aAAa,YAAa,CAAA;AAAA,QAC7B,MAAA;AAAA,QACA,OAAA;AAAA,QACA,KAAA;AAAA,QACA,UAAA;AAAA,QACA,OAAA;AAAA,OACD,CAAA,CAAA;AAAA,aACM,CAAG,EAAA;AAEV,MAAQ,OAAA,CAAA,IAAA,CAAK,4CAA4C,CAAC,CAAA,CAAA;AAAA,KAC5D;AAAA,GACF;AACF;;ACzJA,SAAS,eAAgC,GAAA;AACvC,EAAI,IAAA;AACF,IAAA,OAAO,OAAO,eAAe,CAAA,CAAA;AAAA,GACvB,CAAA,MAAA;AACN,IAAO,OAAA,EAAE,cAAc,MAAM;AAAA,KAAG,EAAA,CAAA;AAAA,GAClC;AACF,CAAA;AAOO,SAAS,YAAiC,GAAA;AAC/C,EAAM,MAAA,UAAA,GAAa,OAAuB,IAAI,CAAA,CAAA;AAC9C,EAAA,MAAM,UAAU,mBAAoB,EAAA,CAAA;AAIpC,EAAA,MAAM,eAAe,eAAgB,EAAA,CAAA;AAErC,EAAA,SAAS,UAAsB,GAAA;AAC7B,IAAI,IAAA,UAAA,CAAW,YAAY,IAAM,EAAA;AAC/B,MAAW,UAAA,CAAA,OAAA,GAAU,IAAI,OAAA,CAAQ,YAAY,CAAA,CAAA;AAAA,KAC/C;AACA,IAAA,OAAO,UAAW,CAAA,OAAA,CAAA;AAAA,GACpB;AAEA,EAAA,MAAM,UAAU,UAAW,EAAA,CAAA;AAG3B,EAAA,OAAA,CAAQ,WAAW,OAAO,CAAA,CAAA;AAE1B,EAAO,OAAA,OAAA,CAAA;AACT;;ACpCO,MAAM,SAAS,MAAoB;AACxC,EAAA,MAAM,gBAAmB,GAAA,mBAAA;AAAA,IACvB,aAAA;AAAA,GACF,CAAA;AACA,EAAA,IAAI,CAAC,gBAAkB,EAAA;AACrB,IAAM,MAAA,IAAI,MAAM,8BAA8B,CAAA,CAAA;AAAA,GAChD;AAEA,EAAM,MAAA,UAAA,GAAa,gBAAiB,CAAA,SAAA,CAAU,CAAC,CAAA,CAAA;AAC/C,EAAA,IAAI,CAAC,UAAY,EAAA;AACf,IAAM,MAAA,IAAI,MAAM,6BAA6B,CAAA,CAAA;AAAA,GAC/C;AACA,EAAO,OAAA,UAAA,CAAA;AACT;;ACZA,MAAM,WAAc,GAAA,0BAAA;AAAA,EAClB,sBAAA;AAAA,EACA,0BAAU,OAA2C,EAAA;AACvD,CAAA,CAAA;AAKA,MAAM,gBAAmB,GAAA,kBAAA,CAAA;AAsBT,SAAA,mBAAA,CACd,SACA,EAAA,IAAA,EACA,IACA,EAAA;AA3DF,EAAA,IAAA,EAAA,CAAA;AA4DE,EAAA,MAAM,aAAgB,GAAA,SAAA,CAAA;AAEtB,EAAA,IAAI,aAAY,EAAc,GAAA,aAAA,CAAA,gBAAgB,MAA9B,IAAmC,GAAA,EAAA,GAAA,WAAA,CAAY,IAAI,SAAS,CAAA,CAAA;AAC5E,EAAA,IAAI,CAAC,SAAW,EAAA;AACd,IAAA,SAAA,GAAY,EAAE,GAAA,kBAAS,IAAA,GAAA,EAAM,EAAA,CAAA;AAC7B,IAAO,MAAA,CAAA,cAAA,CAAe,eAAe,gBAAkB,EAAA;AAAA,MACrD,UAAY,EAAA,KAAA;AAAA,MACZ,YAAc,EAAA,IAAA;AAAA,MACd,QAAU,EAAA,KAAA;AAAA,MACV,KAAO,EAAA,SAAA;AAAA,KACR,CAAA,CAAA;AACD,IAAY,WAAA,CAAA,GAAA,CAAI,WAAW,SAAS,CAAA,CAAA;AAAA,GACtC;AAEA,EAAA,IAAI,SAAU,CAAA,GAAA,CAAI,GAAI,CAAA,IAAI,CAAG,EAAA;AAC3B,IAAM,MAAA,IAAA,GAAO,SAAU,CAAA,WAAA,IAAe,SAAU,CAAA,IAAA,CAAA;AAChD,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,oCAAA,EAAuC,IAAI,CAAA,gBAAA,EAAmB,IAAI,CAAA,CAAA,CAAA;AAAA,KACpE,CAAA;AAAA,GACF;AAEA,EAAU,SAAA,CAAA,GAAA,CAAI,GAAI,CAAA,IAAA,EAAM,IAAI,CAAA,CAAA;AAC9B,CAAA;AAcgB,SAAA,gBAAA,CACd,MACA,IACe,EAAA;AAnGjB,EAAA,IAAA,EAAA,CAAA;AAoGE,EAAA,IAAI,CAAC,IAAM,EAAA;AACT,IAAO,OAAA,KAAA,CAAA,CAAA;AAAA,GACT;AAEA,EAAA,MAAM,YAAa,IAA4B,CAAA,IAAA,CAAA;AAC/C,EAAA,IAAI,CAAC,SAAW,EAAA;AACd,IAAO,OAAA,KAAA,CAAA,CAAA;AAAA,GACT;AAEA,EAAA,MAAM,aAAY,EAAU,GAAA,SAAA,CAAA,gBAAgB,MAA1B,IAA+B,GAAA,EAAA,GAAA,WAAA,CAAY,IAAI,SAAS,CAAA,CAAA;AAC1E,EAAA,IAAI,CAAC,SAAW,EAAA;AACd,IAAO,OAAA,KAAA,CAAA,CAAA;AAAA,GACT;AAEA,EAAO,OAAA,SAAA,CAAU,GAAI,CAAA,GAAA,CAAI,IAAI,CAAA,CAAA;AAC/B;;AC/CO,MAAM,YAA8B,GAAA,0BAAA;AAAA,EACzC,gBAAA;AAAA,EACA,MAAM,OAAO,gBAAgB,CAAA;AAC/B,CAAA;;;;;;;;ACvEA,IAAAA,IAAA,CAAA;AA2BO,MAAM,YAEb,CAAA;AAAA,EAKE,WAAA,CACmB,IACR,MACT,EAAA;AAFiB,IAAA,IAAA,CAAA,EAAA,GAAA,EAAA,CAAA;AACR,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AAJX,IAAAC,eAAA,CAAA,IAAA,EAAUD,IAAgB,EAAA,UAAA,CAAA,CAAA;AAAA,GAKvB;AAAA,EAEH,IAAI,KAAQ,GAAA;AACV,IAAA,OAAO,IAAK,CAAA,EAAA,CAAA;AAAA,GACd;AAAA,EAEA,QAAW,GAAA;AACT,IAAO,OAAA,CAAA,0BAAA,EAA6B,KAAK,EAAE,CAAA,CAAA,CAAA,CAAA;AAAA,GAC7C;AACF,CAAA;AAdYA,IAAA,GAAA,YAAA,CAAA;AAsBL,SAAS,eAQd,MAKmC,EAAA;AAnErC,EAAAA,IAAAA,GAAAA,CAAAA;AAoEE,EAAA,OAAO,IAAI,YAAA;AAAA,IACT,MAAO,CAAA,EAAA;AAAA,IAAA,CACNA,GAAA,GAAA,MAAA,CAAO,MAAP,KAAA,IAAA,GAAAA,MAAiB,EAAC;AAAA,GACrB,CAAA;AACF;;;;;;;;ACxEA,IAAAA,IAAA,CAAA;AA0BA,MAAM,aAAgB,GAAA,OAAA,CAAA;AAKf,MAAM,eAEb,CAAA;AAAA,EAKE,WACmB,CAAA,EAAA,EACR,IACA,EAAA,MAAA,EACA,MACT,EAAA;AAJiB,IAAA,IAAA,CAAA,EAAA,GAAA,EAAA,CAAA;AACR,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA,CAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AANX,IAAAC,eAAA,CAAA,IAAA,EAAUD,IAAgB,EAAA,KAAA,CAAA,CAAA;AAAA,GAOvB;AAAA,EAEH,QAAW,GAAA;AACT,IAAO,OAAA,CAAA,qBAAA,EAAwB,KAAK,EAAE,CAAA,CAAA,CAAA,CAAA;AAAA,GACxC;AACF,CAAA;AAZYA,IAAA,GAAA,YAAA,CAAA;AAiEL,SAAS,kBAGd,MAIkD,EAAA;AAClD,EAAA,MAAM,EAAE,EAAA,EAAI,IAAM,EAAA,MAAA,EAAW,GAAA,MAAA,CAAA;AAI7B,EAAA,MAAM,aAAa,IAChB,CAAA,KAAA,CAAM,GAAG,CAAA,CACT,OAAO,CAAK,CAAA,KAAA,CAAA,CAAE,UAAW,CAAA,GAAG,CAAC,CAC7B,CAAA,GAAA,CAAI,OAAK,CAAE,CAAA,SAAA,CAAU,CAAC,CAAC,CAAA,CAAA;AAC1B,EAAA,MAAM,SAAS,CAAC,GAAG,MAAO,CAAA,MAAA,EAAQ,GAAG,UAAU,CAAA,CAAA;AAE/C,EAAI,IAAA,MAAA,CAAO,OAAO,IAAK,CAAA,CAAA,CAAA,KAAK,WAAW,QAAS,CAAA,CAAW,CAAC,CAAG,EAAA;AAC7D,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,8DAAA;AAAA,KACF,CAAA;AAAA,GACF;AACA,EAAA,IAAI,CAAC,IAAA,CAAK,UAAW,CAAA,GAAG,CAAG,EAAA;AACzB,IAAA,MAAM,IAAI,KAAA,CAAM,CAA8C,2CAAA,EAAA,IAAI,CAAG,CAAA,CAAA,CAAA,CAAA;AAAA,GACvE;AACA,EAAI,IAAA,IAAA,CAAK,QAAS,CAAA,GAAG,CAAG,EAAA;AACtB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAgD,6CAAA,EAAA,IAAI,CAAG,CAAA,CAAA,CAAA,CAAA;AAAA,GACzE;AACA,EAAA,KAAA,MAAW,SAAS,UAAY,EAAA;AAC9B,IAAA,IAAI,CAAC,aAAA,CAAc,IAAK,CAAA,KAAK,CAAG,EAAA;AAC9B,MAAA,MAAM,IAAI,KAAA,CAAM,CAA4C,yCAAA,EAAA,KAAK,CAAG,CAAA,CAAA,CAAA,CAAA;AAAA,KACtE;AAAA,GACF;AAGA,EAAA,MAAM,cAAc,IAAI,eAAA;AAAA,IACtB,EAAA;AAAA,IACA,IAAA;AAAA,IACA,MAAA;AAAA,IACA,MAAA;AAAA,GACF,CAAA;AAIA,EAAO,OAAA,WAAA,CAAA;AACT;;;;;;;;ACnJA,IAAA,EAAA,CAAA;AA2BO,MAAM,oBAIb,CAAA;AAAA,EAKE,WAAA,CACmB,EACR,EAAA,MAAA,EACA,QACT,EAAA;AAHiB,IAAA,IAAA,CAAA,EAAA,GAAA,EAAA,CAAA;AACR,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA,CAAA;AALX,IAAAC,eAAA,CAAA,IAAA,EAAU,EAAgB,EAAA,UAAA,CAAA,CAAA;AAAA,GAMvB;AAAA,EAEH,QAAW,GAAA;AACT,IAAO,OAAA,CAAA,0BAAA,EAA6B,KAAK,EAAE,CAAA,CAAA,CAAA,CAAA;AAAA,GAC7C;AACF,CAAA;AAXY,EAAA,GAAA,YAAA,CAAA;AAuBL,SAAS,uBAId,OAkBqD,EAAA;AA/EvD,EAAAD,IAAAA,GAAAA,CAAAA;AAgFE,EAAA,OAAO,IAAI,oBAAA;AAAA,IACT,OAAQ,CAAA,EAAA;AAAA,IAAA,CACPA,GAAA,GAAA,OAAA,CAAQ,MAAR,KAAA,IAAA,GAAAA,MAAkB,EAAC;AAAA,IACpB,OAAA,CAAQ,QAAQ,QAAQ,CAAA;AAAA,GAC1B,CAAA;AACF;;ACJO,SAAS,YACd,QAI+B,EAAA;AAC/B,EAAM,MAAA,EAAE,QAAS,EAAA,GAAI,WAAY,EAAA,CAAA;AACjC,EAAA,MAAM,gBAAmB,GAAA,mBAAA;AAAA,IACvB,iBAAA;AAAA,GACF,CAAA;AACA,EAAA,IAAI,CAAC,gBAAkB,EAAA;AACrB,IAAM,MAAA,IAAI,MAAM,kCAAkC,CAAA,CAAA;AAAA,GACpD;AAEA,EAAM,MAAA,QAAA,GAAW,gBAAiB,CAAA,SAAA,CAAU,CAAC,CAAA,CAAA;AAC7C,EAAA,MAAM,SAAY,GAAA,OAAA;AAAA,IAChB,MAAM,QAAY,IAAA,QAAA,CAAS,QAAQ,QAAU,EAAA,EAAE,UAAU,CAAA;AAAA,IACzD,CAAC,QAAU,EAAA,QAAA,EAAU,QAAQ,CAAA;AAAA,GAC/B,CAAA;AAEA,EAAA,IAAI,CAAC,gBAAkB,EAAA;AACrB,IAAM,MAAA,IAAI,MAAM,6CAA6C,CAAA,CAAA;AAAA,GAC/D;AACA,EAAA,IAAI,CAAC,QAAU,EAAA;AACb,IAAM,MAAA,IAAI,MAAM,iCAAiC,CAAA,CAAA;AAAA,GACnD;AAEA,EAAM,MAAA,UAAA,GAAa,UAAc,IAAA,QAAA,IAAY,QAAS,CAAA,QAAA,CAAA;AACtD,EAAI,IAAA,CAAC,SAAa,IAAA,CAAC,UAAY,EAAA;AAC7B,IAAA,MAAM,IAAI,KAAA,CAAM,CAAe,YAAA,EAAA,QAAQ,CAAE,CAAA,CAAA,CAAA;AAAA,GAC3C;AAEA,EAAO,OAAA,SAAA,CAAA;AACT;;AC1FO,SAAS,kBACd,SACQ,EAAA;AACR,EAAA,OAAO,SAAU,EAAA,CAAA;AACnB;;;;;;;;ACDa,MAAA,mBAAA,SAA4B,MAAM,SAAwB,CAAA;AAAA,EAAhE,WAAA,GAAA;AAAA,IAAA,KAAA,CAAA,GAAA,SAAA,CAAA,CAAA;AAKL,IAAeC,eAAA,CAAA,IAAA,EAAA,OAAA,EAAA,EAAE,OAAO,KAAU,CAAA,EAAA,CAAA,CAAA;AAElC,IAAAA,eAAA,CAAA,IAAA,EAAA,kBAAA,EAAmB,MAAM;AACvB,MAAA,IAAA,CAAK,QAAS,CAAA,EAAE,KAAO,EAAA,KAAA,CAAA,EAAW,CAAA,CAAA;AAAA,KACpC,CAAA,CAAA;AAAA,GAAA;AAAA,EARA,OAAO,yBAAyB,KAAc,EAAA;AAC5C,IAAA,OAAO,EAAE,KAAM,EAAA,CAAA;AAAA,GACjB;AAAA,EAQA,MAAS,GAAA;AACP,IAAM,MAAA,EAAE,KAAM,EAAA,GAAI,IAAK,CAAA,KAAA,CAAA;AACvB,IAAA,MAAM,EAAE,GAAA,EAAK,MAAO,EAAA,GAAI,IAAK,CAAA,KAAA,CAAA;AAC7B,IAAA,MAAM,EAAE,qBAAA,EAA0B,GAAA,GAAA,CAAI,aAAc,EAAA,CAAA;AAEpD,IAAA,IAAI,KAAO,EAAA;AACT,MACE,uBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,qBAAA;AAAA,QAAA;AAAA,UACC,KAAA;AAAA,UACA,YAAY,IAAK,CAAA,gBAAA;AAAA,UACjB,MAAA;AAAA,SAAA;AAAA,OACF,CAAA;AAAA,KAEJ;AAEA,IAAA,OAAO,KAAK,KAAM,CAAA,QAAA,CAAA;AAAA,GACpB;AACF;;ACHO,SAAS,wBAEd,OAuBe,EAAA;AACf,EAAA,MAAM,EAAE,SAAA,EAAW,UAAY,EAAA,IAAA,EAAS,GAAA,OAAA,CAAA;AACxC,EAAA,OAAO,oBAAqB,CAAA;AAAA,IAC1B,SAAW,EAAA;AAAA,MACT,IAAA,EAAM,MACJ,SAAA,EAAY,CAAA,IAAA;AAAA,QACV,CAAkB,cAAA,KAAA;AAChB,UAAM,MAAA,wBAAA,GAAgC,CAAC,KAAe,KAAA;AACpD,YAAA,MAAM,YAAY,YAAa,EAAA,CAAA;AAG/B,YAAI,IAAA;AACF,cAAA,WAAA,CAAY,UAAU,CAAA,CAAA;AAAA,qBACf,KAAO,EAAA;AACd,cAAA,IAAI,OAAO,KAAA,KAAU,QAAY,IAAA,KAAA,KAAU,IAAM,EAAA;AAC/C,gBAAM,MAAA,EAAE,SAAY,GAAA,KAAA,CAAA;AACpB,gBAAA,IACE,OAAO,OAAY,KAAA,QAAA,IACnB,OAAQ,CAAA,UAAA,CAAW,cAAc,CACjC,EAAA;AACA,kBAAA,MAAM,IAAI,KAAA;AAAA,oBACR,iDAAiD,UAAU,CAAA,kMAAA,CAAA;AAAA,mBAG7D,CAAA;AAAA,iBACF;AAAA,eACF;AACA,cAAM,MAAA,KAAA,CAAA;AAAA,aACR;AAMA,YAAA,SAAA,CAAU,MAAM;AACd,cAAU,SAAA,CAAA,YAAA,CAAa,gCAAgC,EAAE,CAAA,CAAA;AAAA,aAC3D,EAAG,CAAC,SAAS,CAAC,CAAA,CAAA;AAEd,YAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,cAAgB,EAAA,EAAA,GAAG,KAAO,EAAA,CAAA,CAAA;AAAA,WACpC,CAAA;AAEA,UAAA,MAAM,aACJ,GAAA,IAAA,IACC,cAA4C,CAAA,WAAA,IAC7C,eAAe,IACf,IAAA,eAAA,CAAA;AAEF,UAAyB,wBAAA,CAAA,WAAA,GAAc,qBAAqB,aAAa,CAAA,CAAA,CAAA,CAAA;AAEzE,UAAO,OAAA,wBAAA,CAAA;AAAA,SACT;AAAA,QACA,CAAS,KAAA,KAAA;AACP,UAAM,MAAA,wBAAA,GAAgC,CAAC,CAAW,KAAA;AAChD,YAAA,MAAM,MAAM,MAAO,EAAA,CAAA;AACnB,YAAA,MAAM,EAAE,aAAA,EAAkB,GAAA,GAAA,CAAI,aAAc,EAAA,CAAA;AAE5C,YAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,aAAA,EAAA,EAAc,IAAK,EAAA,YAAA,EAAa,KAAc,EAAA,CAAA,CAAA;AAAA,WACxD,CAAA;AACA,UAAO,OAAA,wBAAA,CAAA;AAAA,SACT;AAAA,OACF;AAAA,KACJ;AAAA,IACA,IAAM,EAAA;AAAA,MACJ,iBAAmB,EAAA,UAAA;AAAA,KACrB;AAAA,IACA,IAAA;AAAA,GACD,CAAA,CAAA;AACH,CAAA;AAeO,SAAS,yBAEd,OAce,EAAA;AACf,EAAM,MAAA,EAAE,SAAW,EAAA,IAAA,EAAS,GAAA,OAAA,CAAA;AAC5B,EAAA,OAAO,oBAAqB,CAAA,EAAE,SAAW,EAAA,IAAA,EAAM,CAAA,CAAA;AACjD,CAAA;AAeO,SAAS,qBAEd,OAmBe,EAAA;AACf,EAAA,MAAM,EAAE,IAAA,GAAO,EAAC,EAAG,MAAS,GAAA,OAAA,CAAA;AAC5B,EAAA,IAAI,CAAC,IAAM,EAAA;AAET,IAAQ,OAAA,CAAA,IAAA;AAAA,MACN,0KAAA;AAAA,KAEF,CAAA;AAAA,GACF;AAEA,EAAI,IAAA,SAAA,CAAA;AACJ,EAAI,IAAA,MAAA,IAAU,QAAQ,SAAW,EAAA;AAC/B,IAAM,MAAA,UAAA,GAAa,QAAQ,SAAU,CAAA,IAAA,CAAA;AACrC,IAAY,SAAA,GAAA,IAAA;AAAA,MAAK,MACf,YAAa,CAAA,IAAA,CAAK,gBAAc,EAAE,OAAA,EAAS,WAAY,CAAA,CAAA;AAAA,KACzD,CAAA;AAAA,GACK,MAAA;AACL,IAAA,SAAA,GAAY,QAAQ,SAAU,CAAA,IAAA,CAAA;AAAA,GAChC;AACA,EAAA,MAAM,aACJ,GAAA,IAAA,IACC,SAAuC,CAAA,WAAA,IACxC,UAAU,IACV,IAAA,WAAA,CAAA;AAEF,EAAO,OAAA;AAAA,IACL,OAAO,MAAyB,EAAA;AAC9B,MAAM,MAAA,MAAA,GAAc,CAAC,KAAe,KAAA;AAClC,QAAA,MAAM,MAAM,MAAO,EAAA,CAAA;AACnB,QAAA,MAAM,EAAE,QAAA,EAAa,GAAA,GAAA,CAAI,aAAc,EAAA,CAAA;AAGvC,QAAA,MAAM,aAAa,IAAO,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,IAAA,CAAA,iBAAA,CAAA,CAAA;AAI1B,QACE,uBAAA,KAAA,CAAA,aAAA,CAAC,YAAS,QAAU,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAS,CAC5B,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,mBAAoB,EAAA,EAAA,GAAA,EAAU,MAC7B,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,UAAC,gBAAA;AAAA,UAAA;AAAA,YACC,UAAY,EAAA;AAAA,cACV,QAAA,EAAU,OAAO,KAAM,EAAA;AAAA,cACvB,GAAI,IAAA,IAAQ,EAAE,SAAA,EAAW,IAAK,EAAA;AAAA,cAC9B,GAAI,UAAA,IAAc,EAAE,QAAA,EAAU,WAAW,EAAG,EAAA;AAAA,aAC9C;AAAA,WAAA;AAAA,8CAEC,cAAe,EAAA,EAAA,MAAA,EAAA,sCACb,SAAW,EAAA,EAAA,GAAG,OAAO,CACxB,CAAA;AAAA,SAEJ,CACF,CAAA,CAAA;AAAA,OAEJ,CAAA;AAEA,MAAoB,mBAAA,CAAA,MAAA,EAAQ,eAAe,MAAM,CAAA,CAAA;AACjD,MAAoB,mBAAA,CAAA,MAAA,EAAQ,sBAAsB,IAAI,CAAA,CAAA;AACtD,MAAA,KAAA,MAAW,CAAC,GAAK,EAAA,KAAK,KAAK,MAAO,CAAA,OAAA,CAAQ,IAAI,CAAG,EAAA;AAC/C,QAAoB,mBAAA,CAAA,MAAA,EAAQ,KAAK,KAAK,CAAA,CAAA;AAAA,OACxC;AAEA,MAAO,MAAA,CAAA,WAAA,GAAc,aAAa,aAAa,CAAA,CAAA,CAAA,CAAA;AAC/C,MAAO,OAAA,MAAA,CAAA;AAAA,KACT;AAAA,GACF,CAAA;AACF;;AC7PA,SAAS,cACP,CAAA,QAAA,EACA,eACA,EAAA,QAAA,EACA,WAC8B,EAAA;AAC9B,EAAA,OAAO,QAAS,CAAA,OAAA,CAAQ,QAAQ,CAAA,CAAE,QAAQ,CAAQ,IAAA,KAAA;AAChD,IAAI,IAAA,CAAC,cAAe,CAAA,IAAI,CAAG,EAAA;AACzB,MAAA,OAAO,EAAC,CAAA;AAAA,KACV;AAEA,IAAI,IAAA,IAAA,CAAK,SAAS,QAAU,EAAA;AAC1B,MAAO,OAAA,cAAA;AAAA,QACL,KAAK,KAAM,CAAA,QAAA;AAAA,QACX,eAAA;AAAA,QACA,QAAA;AAAA,QACA,WAAA;AAAA,OACF,CAAA;AAAA,KACF;AAEA,IAAI,IAAA,gBAAA,CAAiB,IAAM,EAAA,qBAAqB,CAAG,EAAA;AACjD,MAAA,MAAM,QAAQ,IAAK,CAAA,KAAA,CAAA;AACnB,MAAA,MAAM,SACJ,GAAA,MAAA,IAAU,KACN,GAAA,eAAA,CAAgB,QAAS,CAAA,KAAA,CAAM,IAAI,CAAA,GACnC,CAAC,eAAA,CAAgB,QAAS,CAAA,KAAA,CAAM,OAAO,CAAA,CAAA;AAC7C,MAAA,IAAI,SAAW,EAAA;AACb,QAAO,OAAA,cAAA;AAAA,UACL,KAAK,KAAM,CAAA,QAAA;AAAA,UACX,eAAA;AAAA,UACA,QAAA;AAAA,UACA,WAAA;AAAA,SACF,CAAA;AAAA,OACF;AACA,MAAA,OAAO,EAAC,CAAA;AAAA,KACV;AAEA,IAAA,IAAI,QAAa,KAAA,KAAA,CAAA,IAAa,QAAS,CAAA,IAAI,CAAG,EAAA;AAC5C,MAAA,OAAO,CAAC,IAAI,CAAA,CAAA;AAAA,KACd;AAEA,IAAA,IAAI,WAAa,EAAA;AACf,MAAM,MAAA,IAAI,MAAM,WAAW,CAAA,CAAA;AAAA,KAC7B;AAEA,IAAO,OAAA,cAAA;AAAA,MACL,KAAK,KAAM,CAAA,QAAA;AAAA,MACX,eAAA;AAAA,MACA,QAAA;AAAA,MACA,WAAA;AAAA,KACF,CAAA;AAAA,GACD,CAAA,CAAA;AACH,CAAA;AA0DA,MAAM,UAAwC,CAAA;AAAA,EAC5C,WAAA,CACmB,MACA,eACjB,EAAA;AAFiB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA,CAAA;AACA,IAAA,IAAA,CAAA,eAAA,GAAA,eAAA,CAAA;AAAA,GAChB;AAAA,EAEH,sBAAsB,KAAkD,EAAA;AACtE,IAAA,MAAM,SAAY,GAAA,cAAA;AAAA,MAChB,IAAK,CAAA,IAAA;AAAA,MACL,IAAK,CAAA,eAAA;AAAA,MACL,CAAQ,IAAA,KAAA,gBAAA,CAAiB,IAAM,EAAA,KAAA,CAAM,GAAG,CAAM,KAAA,KAAA,CAAA;AAAA,MAC9C,KAAM,CAAA,eAAA;AAAA,KACR,CAAA;AACA,IAAA,OAAO,IAAI,UAAA,CAAW,SAAW,EAAA,IAAA,CAAK,eAAe,CAAA,CAAA;AAAA,GACvD;AAAA,EAEA,kBAAqB,KAA6B,EAAA;AAChD,IAAA,MAAM,SAAY,GAAA,cAAA;AAAA,MAChB,IAAK,CAAA,IAAA;AAAA,MACL,IAAK,CAAA,eAAA;AAAA,MACL,CAAQ,IAAA,KAAA,gBAAA,CAAiB,IAAM,EAAA,KAAA,CAAM,GAAG,CAAM,KAAA,KAAA,CAAA;AAAA,KAChD,CAAA;AACA,IAAA,OAAO,SACJ,CAAA,GAAA,CAAI,CAAQ,IAAA,KAAA,gBAAA,CAAoB,IAAM,EAAA,KAAA,CAAM,GAAG,CAAC,CAChD,CAAA,MAAA,CAAO,CAAC,IAAA,KAAmC,SAAS,KAAS,CAAA,CAAA,CAAA;AAAA,GAClE;AAAA,EAEA,WAEE,GAAA;AACA,IAAA,OAAO,cAAe,CAAA,IAAA,CAAK,IAAM,EAAA,IAAA,CAAK,eAAe,CAAA,CAAA;AAAA,GAGvD;AACF,CAAA;AAwBO,SAAS,gBACd,CAAA,IAAA,EACA,QACA,EAAA,YAAA,GAAsB,EACtB,EAAA;AACA,EAAM,MAAA,eAAA,GAAkB,OAAO,kBAAkB,CAAA,CAAA;AACjD,EAAA,MAAM,QAAW,GAAA,IAAI,UAAW,CAAA,IAAA,EAAM,eAAe,CAAA,CAAA;AAErD,EAAO,OAAA,OAAA,CAAQ,MAAM,QAAS,CAAA,QAAQ,GAAG,CAAC,IAAA,EAAM,GAAG,YAAY,CAAC,CAAA,CAAA;AAClE;;;;;;;;AC9KO,MAAM,UAKb,CAAA;AAAA,EACE,YACmB,MAKjB,EAAA;AALiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AAOnB,IAAQ,aAAA,CAAA,IAAA,EAAA,SAAA,CAAA,CAAA;AAAA,GAFL;AAAA,EAIH,KAAgB,GAAA;AACd,IAAA,OAAO,KAAK,MAAO,CAAA,EAAA,CAAA;AAAA,GACrB;AAAA,EAEA,OAAmC,GAAA;AAjDrC,IAAA,IAAA,EAAA,CAAA;AAkDI,IAAA,OAAA,CAAO,EAAK,GAAA,IAAA,CAAA,MAAA,CAAO,IAAZ,KAAA,IAAA,GAAA,EAAA,GAAoB,EAAC,CAAA;AAAA,GAC9B;AAAA,EAEA,eAAqD,GAAA;AArDvD,IAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AAsDI,IAAA,OAAA,CAAO,gBAAK,MAAO,CAAA,YAAA,KAAZ,IAA0B,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,KAAA,EAAA,KAA1B,YAAqC,EAAC,CAAA;AAAA,GAC/C;AAAA,EAEA,IAAI,MAAiB,GAAA;AAzDvB,IAAA,IAAA,EAAA,CAAA;AA0DI,IAAA,OAAA,CAAO,EAAK,GAAA,IAAA,CAAA,MAAA,CAAO,MAAZ,KAAA,IAAA,GAAA,EAAA,GAAuB,EAAC,CAAA;AAAA,GACjC;AAAA,EAEA,IAAI,cAAiC,GAAA;AA7DvC,IAAA,IAAA,EAAA,CAAA;AA8DI,IAAA,OAAA,CAAO,EAAK,GAAA,IAAA,CAAA,MAAA,CAAO,cAAZ,KAAA,IAAA,GAAA,EAAA,GAA+B,EAAC,CAAA;AAAA,GACzC;AAAA,EAEA,QAAW,SAA4B,EAAA;AACrC,IAAO,OAAA,SAAA,CAAU,OAAO,IAAI,CAAA,CAAA;AAAA,GAC9B;AAAA,EAEA,0BAA0B,OAAmC,EAAA;AAC3D,IAAI,IAAA,IAAA,CAAK,OAAO,uBAAyB,EAAA;AACvC,MAAA,IAAA,CAAK,OAAU,GAAA,IAAA,CAAK,MAAO,CAAA,uBAAA,CAAwB,OAAO,CAAA,CAAA;AAAA,KAC5D;AAAA,GACF;AAAA,EAEA,gBAAuB,GAAA;AA3EzB,IAAA,IAAA,EAAA,CAAA;AA4EI,IAAA,IAAI,IAAK,CAAA,MAAA,CAAO,uBAA2B,IAAA,CAAC,KAAK,OAAS,EAAA;AACxD,MAAK,IAAA,CAAA,OAAA,GAAU,IAAK,CAAA,MAAA,CAAO,uBAAwB,EAAA,CAAA;AAAA,KACrD;AACA,IAAO,OAAA,CAAA,EAAA,GAAA,IAAA,CAAK,OAAL,KAAA,IAAA,GAAA,EAAA,GAAgB,EAAC,CAAA;AAAA,GAC1B;AAAA,EAEA,QAAW,GAAA;AACT,IAAO,OAAA,CAAA,OAAA,EAAU,IAAK,CAAA,MAAA,CAAO,EAAE,CAAA,CAAA,CAAA,CAAA;AAAA,GACjC;AACF,CAAA;AAQO,SAAS,aAKd,MAC6D,EAAA;AAC7D,EAAO,OAAA,IAAI,WAAW,MAAM,CAAA,CAAA;AAC9B;;;;"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@backstage/core-plugin-api",
3
3
  "description": "Core API used by Backstage plugins",
4
- "version": "1.6.0-next.2",
4
+ "version": "1.6.0",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -33,6 +33,7 @@
33
33
  "license": "Apache-2.0",
34
34
  "main": "./dist/index.esm.js",
35
35
  "types": "./dist/index.d.ts",
36
+ "sideEffects": false,
36
37
  "scripts": {
37
38
  "build": "backstage-cli package build",
38
39
  "lint": "backstage-cli package lint",
@@ -43,14 +44,13 @@
43
44
  "start": "backstage-cli package start"
44
45
  },
45
46
  "dependencies": {
46
- "@backstage/config": "^1.1.0-next.1",
47
- "@backstage/types": "^1.1.0",
48
- "@backstage/version-bridge": "^1.0.4",
47
+ "@backstage/config": "^1.1.0",
48
+ "@backstage/types": "^1.1.1",
49
+ "@backstage/version-bridge": "^1.0.5",
49
50
  "@types/react": "^16.13.1 || ^17.0.0",
50
51
  "history": "^5.0.0",
51
52
  "i18next": "^22.4.15",
52
53
  "prop-types": "^15.7.2",
53
- "react-i18next": "^12.3.1",
54
54
  "zen-observable": "^0.10.0"
55
55
  },
56
56
  "peerDependencies": {
@@ -59,9 +59,9 @@
59
59
  "react-router-dom": "6.0.0-beta.0 || ^6.3.0"
60
60
  },
61
61
  "devDependencies": {
62
- "@backstage/cli": "^0.22.13-next.2",
63
- "@backstage/core-app-api": "^1.10.0-next.2",
64
- "@backstage/test-utils": "^1.4.3-next.2",
62
+ "@backstage/cli": "^0.22.13",
63
+ "@backstage/core-app-api": "^1.10.0",
64
+ "@backstage/test-utils": "^1.4.3",
65
65
  "@testing-library/dom": "^8.0.0",
66
66
  "@testing-library/jest-dom": "^5.10.1",
67
67
  "@testing-library/react": "^12.1.3",