@backstage/frontend-plugin-api 0.7.0-next.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/CHANGELOG.md +244 -0
  2. package/dist/blueprints/ApiBlueprint.esm.js +23 -0
  3. package/dist/blueprints/ApiBlueprint.esm.js.map +1 -0
  4. package/dist/blueprints/AppRootElementBlueprint.esm.js +18 -0
  5. package/dist/blueprints/AppRootElementBlueprint.esm.js.map +1 -0
  6. package/dist/blueprints/AppRootWrapperBlueprint.esm.js +25 -0
  7. package/dist/blueprints/AppRootWrapperBlueprint.esm.js.map +1 -0
  8. package/dist/blueprints/IconBundleBlueprint.esm.js.map +1 -0
  9. package/dist/blueprints/NavItemBlueprint.esm.js +34 -0
  10. package/dist/blueprints/NavItemBlueprint.esm.js.map +1 -0
  11. package/dist/blueprints/NavLogoBlueprint.esm.js +27 -0
  12. package/dist/blueprints/NavLogoBlueprint.esm.js.map +1 -0
  13. package/dist/blueprints/PageBlueprint.esm.js +34 -0
  14. package/dist/blueprints/PageBlueprint.esm.js.map +1 -0
  15. package/dist/blueprints/RouterBlueprint.esm.js +21 -0
  16. package/dist/blueprints/RouterBlueprint.esm.js.map +1 -0
  17. package/dist/blueprints/SignInPageBlueprint.esm.js +28 -0
  18. package/dist/blueprints/SignInPageBlueprint.esm.js.map +1 -0
  19. package/dist/blueprints/ThemeBlueprint.esm.js +22 -0
  20. package/dist/blueprints/ThemeBlueprint.esm.js.map +1 -0
  21. package/dist/blueprints/TranslationBlueprint.esm.js +21 -0
  22. package/dist/blueprints/TranslationBlueprint.esm.js.map +1 -0
  23. package/dist/components/ExtensionBoundary.esm.js +10 -1
  24. package/dist/components/ExtensionBoundary.esm.js.map +1 -1
  25. package/dist/extensions/createApiExtension.esm.js +3 -5
  26. package/dist/extensions/createApiExtension.esm.js.map +1 -1
  27. package/dist/extensions/createAppRootElementExtension.esm.js.map +1 -1
  28. package/dist/extensions/createAppRootWrapperExtension.esm.js +3 -3
  29. package/dist/extensions/createAppRootWrapperExtension.esm.js.map +1 -1
  30. package/dist/extensions/createComponentExtension.esm.js.map +1 -1
  31. package/dist/extensions/createNavItemExtension.esm.js +3 -3
  32. package/dist/extensions/createNavItemExtension.esm.js.map +1 -1
  33. package/dist/extensions/createNavLogoExtension.esm.js +3 -3
  34. package/dist/extensions/createNavLogoExtension.esm.js.map +1 -1
  35. package/dist/extensions/createPageExtension.esm.js.map +1 -1
  36. package/dist/extensions/createRouterExtension.esm.js +3 -3
  37. package/dist/extensions/createRouterExtension.esm.js.map +1 -1
  38. package/dist/extensions/createSignInPageExtension.esm.js +12 -2
  39. package/dist/extensions/createSignInPageExtension.esm.js.map +1 -1
  40. package/dist/extensions/createThemeExtension.esm.js +3 -5
  41. package/dist/extensions/createThemeExtension.esm.js.map +1 -1
  42. package/dist/extensions/createTranslationExtension.esm.js +3 -3
  43. package/dist/extensions/createTranslationExtension.esm.js.map +1 -1
  44. package/dist/index.d.ts +517 -128
  45. package/dist/index.esm.js +12 -2
  46. package/dist/index.esm.js.map +1 -1
  47. package/dist/wiring/createExtension.esm.js +75 -8
  48. package/dist/wiring/createExtension.esm.js.map +1 -1
  49. package/dist/wiring/createExtensionBlueprint.esm.js +38 -27
  50. package/dist/wiring/createExtensionBlueprint.esm.js.map +1 -1
  51. package/dist/wiring/createExtensionDataContainer.esm.js +31 -0
  52. package/dist/wiring/createExtensionDataContainer.esm.js.map +1 -0
  53. package/dist/wiring/createExtensionDataRef.esm.js.map +1 -1
  54. package/dist/wiring/createFrontendPlugin.esm.js +59 -0
  55. package/dist/wiring/createFrontendPlugin.esm.js.map +1 -0
  56. package/dist/wiring/resolveExtensionDefinition.esm.js +7 -1
  57. package/dist/wiring/resolveExtensionDefinition.esm.js.map +1 -1
  58. package/dist/wiring/resolveInputOverrides.esm.js +76 -0
  59. package/dist/wiring/resolveInputOverrides.esm.js.map +1 -0
  60. package/package.json +6 -6
  61. package/dist/extensions/IconBundleBlueprint.esm.js.map +0 -1
  62. package/dist/wiring/createPlugin.esm.js +0 -35
  63. package/dist/wiring/createPlugin.esm.js.map +0 -1
  64. /package/dist/{extensions → blueprints}/IconBundleBlueprint.esm.js +0 -0
@@ -0,0 +1,76 @@
1
+ import { createExtensionDataContainer } from './createExtensionDataContainer.esm.js';
2
+
3
+ function expectArray(value) {
4
+ return value;
5
+ }
6
+ function expectItem(value) {
7
+ return value;
8
+ }
9
+ function resolveInputOverrides(declaredInputs, inputs, inputOverrides) {
10
+ if (!declaredInputs || !inputs || !inputOverrides) {
11
+ return inputs;
12
+ }
13
+ const newInputs = {};
14
+ for (const name in declaredInputs) {
15
+ if (!Object.hasOwn(declaredInputs, name)) {
16
+ continue;
17
+ }
18
+ const declaredInput = declaredInputs[name];
19
+ const providedData = inputOverrides[name];
20
+ if (declaredInput.config.singleton) {
21
+ const originalInput = expectItem(inputs[name]);
22
+ if (providedData) {
23
+ const providedContainer = createExtensionDataContainer(
24
+ providedData,
25
+ declaredInput.extensionData
26
+ );
27
+ if (!originalInput) {
28
+ throw new Error(
29
+ `attempted to override data of input '${name}' but it is not present in the original inputs`
30
+ );
31
+ }
32
+ newInputs[name] = Object.assign(providedContainer, {
33
+ node: originalInput.node
34
+ });
35
+ }
36
+ } else {
37
+ const originalInput = expectArray(inputs[name]);
38
+ if (!Array.isArray(providedData)) {
39
+ throw new Error(
40
+ `override data provided for input '${name}' must be an array`
41
+ );
42
+ }
43
+ if (providedData.length === 0) {
44
+ newInputs[name] = [];
45
+ } else {
46
+ const withNodesCount = providedData.filter((d) => "node" in d).length;
47
+ if (withNodesCount === 0) {
48
+ if (originalInput.length !== providedData.length) {
49
+ throw new Error(
50
+ `override data provided for input '${name}' must match the length of the original inputs`
51
+ );
52
+ }
53
+ newInputs[name] = providedData.map((data, i) => {
54
+ const providedContainer = createExtensionDataContainer(
55
+ data,
56
+ declaredInput.extensionData
57
+ );
58
+ return Object.assign(providedContainer, {
59
+ node: originalInput[i].node
60
+ });
61
+ });
62
+ } else if (withNodesCount === providedData.length) {
63
+ newInputs[name] = providedData;
64
+ } else {
65
+ throw new Error(
66
+ `override data for input '${name}' may not mix forwarded inputs with data overrides`
67
+ );
68
+ }
69
+ }
70
+ }
71
+ }
72
+ return newInputs;
73
+ }
74
+
75
+ export { resolveInputOverrides };
76
+ //# sourceMappingURL=resolveInputOverrides.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveInputOverrides.esm.js","sources":["../../src/wiring/resolveInputOverrides.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AppNode } from '../apis';\nimport { Expand } from '../types';\nimport { ResolvedExtensionInput } from './createExtension';\nimport {\n ExtensionDataContainer,\n createExtensionDataContainer,\n} from './createExtensionDataContainer';\nimport {\n AnyExtensionDataRef,\n ExtensionDataRefToValue,\n ExtensionDataValue,\n} from './createExtensionDataRef';\nimport { ExtensionInput } from './createExtensionInput';\n\n/** @public */\nexport type ResolveInputValueOverrides<\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n } = {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n> = Expand<\n {\n [KName in keyof TInputs as TInputs[KName] extends ExtensionInput<\n any,\n {\n optional: infer IOptional extends boolean;\n singleton: boolean;\n }\n >\n ? IOptional extends true\n ? never\n : KName\n : never]: TInputs[KName] extends ExtensionInput<\n infer IDataRefs,\n { optional: boolean; singleton: infer ISingleton extends boolean }\n >\n ? ISingleton extends true\n ? Iterable<ExtensionDataRefToValue<IDataRefs>>\n : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>>\n : never;\n } & {\n [KName in keyof TInputs as TInputs[KName] extends ExtensionInput<\n any,\n {\n optional: infer IOptional extends boolean;\n singleton: boolean;\n }\n >\n ? IOptional extends true\n ? KName\n : never\n : never]?: TInputs[KName] extends ExtensionInput<\n infer IDataRefs,\n { optional: boolean; singleton: infer ISingleton extends boolean }\n >\n ? ISingleton extends true\n ? Iterable<ExtensionDataRefToValue<IDataRefs>>\n : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>>\n : never;\n }\n>;\n\nfunction expectArray<T>(value: T | T[]): T[] {\n return value as T[];\n}\nfunction expectItem<T>(value: T | T[]): T {\n return value as T;\n}\n\n/** @internal */\nexport function resolveInputOverrides(\n declaredInputs?: {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n inputs?: {\n [KName in string]?:\n | ({ node: AppNode } & ExtensionDataContainer<any>)\n | Array<{ node: AppNode } & ExtensionDataContainer<any>>;\n },\n inputOverrides?: ResolveInputValueOverrides,\n) {\n if (!declaredInputs || !inputs || !inputOverrides) {\n return inputs;\n }\n\n const newInputs: typeof inputs = {};\n for (const name in declaredInputs) {\n if (!Object.hasOwn(declaredInputs, name)) {\n continue;\n }\n const declaredInput = declaredInputs[name];\n const providedData = inputOverrides[name];\n if (declaredInput.config.singleton) {\n const originalInput = expectItem(inputs[name]);\n if (providedData) {\n const providedContainer = createExtensionDataContainer(\n providedData as Iterable<ExtensionDataValue<any, any>>,\n declaredInput.extensionData,\n );\n if (!originalInput) {\n throw new Error(\n `attempted to override data of input '${name}' but it is not present in the original inputs`,\n );\n }\n newInputs[name] = Object.assign(providedContainer, {\n node: (originalInput as ResolvedExtensionInput<any>).node,\n }) as any;\n }\n } else {\n const originalInput = expectArray(inputs[name]);\n if (!Array.isArray(providedData)) {\n throw new Error(\n `override data provided for input '${name}' must be an array`,\n );\n }\n\n // Regular inputs can be overridden in two different ways:\n // 1) Forward a subset of the original inputs in a new order\n // 2) Provide new data for each original input\n\n // First check if all inputs are being removed\n if (providedData.length === 0) {\n newInputs[name] = [];\n } else {\n // Check how many of the provided data items have a node property, i.e. is a forwarded input\n const withNodesCount = providedData.filter(d => 'node' in d).length;\n if (withNodesCount === 0) {\n if (originalInput.length !== providedData.length) {\n throw new Error(\n `override data provided for input '${name}' must match the length of the original inputs`,\n );\n }\n newInputs[name] = providedData.map((data, i) => {\n const providedContainer = createExtensionDataContainer(\n data as Iterable<ExtensionDataValue<any, any>>,\n declaredInput.extensionData,\n );\n return Object.assign(providedContainer, {\n node: (originalInput[i] as ResolvedExtensionInput<any>).node,\n }) as any;\n });\n } else if (withNodesCount === providedData.length) {\n newInputs[name] = providedData as any;\n } else {\n throw new Error(\n `override data for input '${name}' may not mix forwarded inputs with data overrides`,\n );\n }\n }\n }\n }\n return newInputs;\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/frontend-plugin-api",
3
- "version": "0.7.0-next.2",
3
+ "version": "0.7.0",
4
4
  "backstage": {
5
5
  "role": "web-library"
6
6
  },
@@ -31,7 +31,7 @@
31
31
  "test": "backstage-cli package test"
32
32
  },
33
33
  "dependencies": {
34
- "@backstage/core-components": "^0.14.10-next.0",
34
+ "@backstage/core-components": "^0.14.10",
35
35
  "@backstage/core-plugin-api": "^1.9.3",
36
36
  "@backstage/types": "^1.1.1",
37
37
  "@backstage/version-bridge": "^1.0.8",
@@ -42,10 +42,10 @@
42
42
  "zod-to-json-schema": "^3.21.4"
43
43
  },
44
44
  "devDependencies": {
45
- "@backstage/cli": "^0.27.0-next.3",
46
- "@backstage/frontend-app-api": "^0.7.5-next.2",
47
- "@backstage/frontend-test-utils": "^0.1.12-next.2",
48
- "@backstage/test-utils": "^1.5.10-next.2",
45
+ "@backstage/cli": "^0.27.0",
46
+ "@backstage/frontend-app-api": "^0.8.0",
47
+ "@backstage/frontend-test-utils": "^0.1.12",
48
+ "@backstage/test-utils": "^1.5.10",
49
49
  "@testing-library/jest-dom": "^6.0.0",
50
50
  "@testing-library/react": "^15.0.0",
51
51
  "history": "^5.3.0"
@@ -1 +0,0 @@
1
- {"version":3,"file":"IconBundleBlueprint.esm.js","sources":["../../src/extensions/IconBundleBlueprint.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { IconComponent } from '../icons';\nimport { createExtensionBlueprint, createExtensionDataRef } from '../wiring';\n\nconst iconsDataRef = createExtensionDataRef<{\n [key in string]: IconComponent;\n}>().with({ id: 'core.icons' });\n\n/** @public */\nexport const IconBundleBlueprint = createExtensionBlueprint({\n kind: 'icon-bundle',\n namespace: 'app',\n attachTo: { id: 'app', input: 'icons' },\n output: [iconsDataRef],\n config: {\n schema: {\n icons: z => z.string().default('blob'),\n test: z => z.string(),\n },\n },\n factory: (params: { icons: { [key in string]: IconComponent } }) => [\n iconsDataRef(params.icons),\n ],\n dataRefs: {\n icons: iconsDataRef,\n },\n});\n"],"names":[],"mappings":";;;;;;AAkBA,MAAM,eAAe,sBAElB,EAAA,CAAE,KAAK,EAAE,EAAA,EAAI,cAAc,CAAA,CAAA;AAGvB,MAAM,sBAAsB,wBAAyB,CAAA;AAAA,EAC1D,IAAM,EAAA,aAAA;AAAA,EACN,SAAW,EAAA,KAAA;AAAA,EACX,QAAU,EAAA,EAAE,EAAI,EAAA,KAAA,EAAO,OAAO,OAAQ,EAAA;AAAA,EACtC,MAAA,EAAQ,CAAC,YAAY,CAAA;AAAA,EACrB,MAAQ,EAAA;AAAA,IACN,MAAQ,EAAA;AAAA,MACN,OAAO,CAAK,CAAA,KAAA,CAAA,CAAE,MAAO,EAAA,CAAE,QAAQ,MAAM,CAAA;AAAA,MACrC,IAAA,EAAM,CAAK,CAAA,KAAA,CAAA,CAAE,MAAO,EAAA;AAAA,KACtB;AAAA,GACF;AAAA,EACA,OAAA,EAAS,CAAC,MAA0D,KAAA;AAAA,IAClE,YAAA,CAAa,OAAO,KAAK,CAAA;AAAA,GAC3B;AAAA,EACA,QAAU,EAAA;AAAA,IACR,KAAO,EAAA,YAAA;AAAA,GACT;AACF,CAAC;;;;"}
@@ -1,35 +0,0 @@
1
- import { resolveExtensionDefinition } from './resolveExtensionDefinition.esm.js';
2
-
3
- function createPlugin(options) {
4
- const extensions = (options.extensions ?? []).map(
5
- (def) => resolveExtensionDefinition(def, { namespace: options.id })
6
- );
7
- const extensionIds = extensions.map((e) => e.id);
8
- if (extensionIds.length !== new Set(extensionIds).size) {
9
- const duplicates = Array.from(
10
- new Set(
11
- extensionIds.filter((id, index) => extensionIds.indexOf(id) !== index)
12
- )
13
- );
14
- throw new Error(
15
- `Plugin '${options.id}' provided duplicate extensions: ${duplicates.join(
16
- ", "
17
- )}`
18
- );
19
- }
20
- return {
21
- $$type: "@backstage/BackstagePlugin",
22
- version: "v1",
23
- id: options.id,
24
- routes: options.routes ?? {},
25
- externalRoutes: options.externalRoutes ?? {},
26
- featureFlags: options.featureFlags ?? [],
27
- extensions,
28
- toString() {
29
- return `Plugin{id=${options.id}}`;
30
- }
31
- };
32
- }
33
-
34
- export { createPlugin };
35
- //# sourceMappingURL=createPlugin.esm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createPlugin.esm.js","sources":["../../src/wiring/createPlugin.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 { ExtensionDefinition } from './createExtension';\nimport {\n Extension,\n resolveExtensionDefinition,\n} from './resolveExtensionDefinition';\nimport {\n AnyExternalRoutes,\n AnyRoutes,\n BackstagePlugin,\n FeatureFlagConfig,\n} from './types';\n\n/** @public */\nexport interface PluginOptions<\n Routes extends AnyRoutes,\n ExternalRoutes extends AnyExternalRoutes,\n> {\n id: string;\n routes?: Routes;\n externalRoutes?: ExternalRoutes;\n extensions?: ExtensionDefinition<any, any>[];\n featureFlags?: FeatureFlagConfig[];\n}\n\n/** @public */\nexport interface InternalBackstagePlugin<\n Routes extends AnyRoutes = AnyRoutes,\n ExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes,\n> extends BackstagePlugin<Routes, ExternalRoutes> {\n readonly version: 'v1';\n readonly extensions: Extension<unknown>[];\n readonly featureFlags: FeatureFlagConfig[];\n}\n\n/** @public */\nexport function createPlugin<\n Routes extends AnyRoutes = {},\n ExternalRoutes extends AnyExternalRoutes = {},\n>(\n options: PluginOptions<Routes, ExternalRoutes>,\n): BackstagePlugin<Routes, ExternalRoutes> {\n const extensions = (options.extensions ?? []).map(def =>\n resolveExtensionDefinition(def, { namespace: options.id }),\n );\n\n const extensionIds = extensions.map(e => e.id);\n if (extensionIds.length !== new Set(extensionIds).size) {\n const duplicates = Array.from(\n new Set(\n extensionIds.filter((id, index) => extensionIds.indexOf(id) !== index),\n ),\n );\n // TODO(Rugvip): This could provide some more information about the kind + name of the extensions\n throw new Error(\n `Plugin '${options.id}' provided duplicate extensions: ${duplicates.join(\n ', ',\n )}`,\n );\n }\n\n return {\n $$type: '@backstage/BackstagePlugin',\n version: 'v1',\n id: options.id,\n routes: options.routes ?? ({} as Routes),\n externalRoutes: options.externalRoutes ?? ({} as ExternalRoutes),\n featureFlags: options.featureFlags ?? [],\n extensions,\n toString() {\n return `Plugin{id=${options.id}}`;\n },\n } as InternalBackstagePlugin<Routes, ExternalRoutes>;\n}\n\n/** @internal */\nexport function toInternalBackstagePlugin(\n plugin: BackstagePlugin,\n): InternalBackstagePlugin {\n const internal = plugin as InternalBackstagePlugin;\n if (internal.$$type !== '@backstage/BackstagePlugin') {\n throw new Error(`Invalid plugin instance, bad type '${internal.$$type}'`);\n }\n if (internal.version !== 'v1') {\n throw new Error(\n `Invalid plugin instance, bad version '${internal.version}'`,\n );\n }\n return internal;\n}\n"],"names":[],"mappings":";;AAmDO,SAAS,aAId,OACyC,EAAA;AACzC,EAAA,MAAM,UAAc,GAAA,CAAA,OAAA,CAAQ,UAAc,IAAA,EAAI,EAAA,GAAA;AAAA,IAAI,SAChD,0BAA2B,CAAA,GAAA,EAAK,EAAE,SAAW,EAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,GAC3D,CAAA;AAEA,EAAA,MAAM,YAAe,GAAA,UAAA,CAAW,GAAI,CAAA,CAAA,CAAA,KAAK,EAAE,EAAE,CAAA,CAAA;AAC7C,EAAA,IAAI,aAAa,MAAW,KAAA,IAAI,GAAI,CAAA,YAAY,EAAE,IAAM,EAAA;AACtD,IAAA,MAAM,aAAa,KAAM,CAAA,IAAA;AAAA,MACvB,IAAI,GAAA;AAAA,QACF,YAAA,CAAa,OAAO,CAAC,EAAA,EAAI,UAAU,YAAa,CAAA,OAAA,CAAQ,EAAE,CAAA,KAAM,KAAK,CAAA;AAAA,OACvE;AAAA,KACF,CAAA;AAEA,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAW,QAAA,EAAA,OAAA,CAAQ,EAAE,CAAA,iCAAA,EAAoC,UAAW,CAAA,IAAA;AAAA,QAClE,IAAA;AAAA,OACD,CAAA,CAAA;AAAA,KACH,CAAA;AAAA,GACF;AAEA,EAAO,OAAA;AAAA,IACL,MAAQ,EAAA,4BAAA;AAAA,IACR,OAAS,EAAA,IAAA;AAAA,IACT,IAAI,OAAQ,CAAA,EAAA;AAAA,IACZ,MAAA,EAAQ,OAAQ,CAAA,MAAA,IAAW,EAAC;AAAA,IAC5B,cAAA,EAAgB,OAAQ,CAAA,cAAA,IAAmB,EAAC;AAAA,IAC5C,YAAA,EAAc,OAAQ,CAAA,YAAA,IAAgB,EAAC;AAAA,IACvC,UAAA;AAAA,IACA,QAAW,GAAA;AACT,MAAO,OAAA,CAAA,UAAA,EAAa,QAAQ,EAAE,CAAA,CAAA,CAAA,CAAA;AAAA,KAChC;AAAA,GACF,CAAA;AACF;;;;"}