@backstage/frontend-app-api 0.8.0 → 0.9.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +64 -0
- package/dist/core-app-api/src/apis/system/ApiRegistry.esm.js +50 -0
- package/dist/core-app-api/src/apis/system/ApiRegistry.esm.js.map +1 -0
- package/dist/extensions/Root.esm.js +18 -0
- package/dist/extensions/Root.esm.js.map +1 -0
- package/dist/frontend-plugin-api/src/wiring/createExtension.esm.js.map +1 -1
- package/dist/frontend-plugin-api/src/wiring/createExtensionOverrides.esm.js.map +1 -1
- package/dist/frontend-plugin-api/src/wiring/createFrontendModule.esm.js +25 -0
- package/dist/frontend-plugin-api/src/wiring/createFrontendModule.esm.js.map +1 -0
- package/dist/frontend-plugin-api/src/wiring/createFrontendPlugin.esm.js +10 -3
- package/dist/frontend-plugin-api/src/wiring/createFrontendPlugin.esm.js.map +1 -1
- package/dist/frontend-plugin-api/src/wiring/resolveExtensionDefinition.esm.js.map +1 -1
- package/dist/index.d.ts +22 -49
- package/dist/index.esm.js +1 -1
- package/dist/routing/collectRouteIds.esm.js +2 -1
- package/dist/routing/collectRouteIds.esm.js.map +1 -1
- package/dist/tree/instantiateAppNodeTree.esm.js +8 -5
- package/dist/tree/instantiateAppNodeTree.esm.js.map +1 -1
- package/dist/tree/resolveAppNodeSpecs.esm.js +42 -5
- package/dist/tree/resolveAppNodeSpecs.esm.js.map +1 -1
- package/dist/tree/resolveAppTree.esm.js +40 -20
- package/dist/tree/resolveAppTree.esm.js.map +1 -1
- package/dist/wiring/createSpecializedApp.esm.js +188 -0
- package/dist/wiring/createSpecializedApp.esm.js.map +1 -0
- package/package.json +6 -8
- package/dist/apis/implementations/ComponentsApi/DefaultComponentsApi.esm.js +0 -30
- package/dist/apis/implementations/ComponentsApi/DefaultComponentsApi.esm.js.map +0 -1
- package/dist/apis/implementations/IconsApi/DefaultIconsApi.esm.js +0 -15
- package/dist/apis/implementations/IconsApi/DefaultIconsApi.esm.js.map +0 -1
- package/dist/app/src/components/Root/LogoFull.esm.js +0 -33
- package/dist/app/src/components/Root/LogoFull.esm.js.map +0 -1
- package/dist/app/src/components/Root/LogoIcon.esm.js +0 -33
- package/dist/app/src/components/Root/LogoIcon.esm.js.map +0 -1
- package/dist/app-defaults/src/defaults/apis.esm.js +0 -221
- package/dist/app-defaults/src/defaults/apis.esm.js.map +0 -1
- package/dist/app-defaults/src/defaults/components.esm.js +0 -46
- package/dist/app-defaults/src/defaults/components.esm.js.map +0 -1
- package/dist/app-defaults/src/defaults/icons.esm.js +0 -51
- package/dist/app-defaults/src/defaults/icons.esm.js.map +0 -1
- package/dist/core-app-api/src/apis/implementations/AppLanguageApi/AppLanguageSelector.esm.js +0 -89
- package/dist/core-app-api/src/apis/implementations/AppLanguageApi/AppLanguageSelector.esm.js.map +0 -1
- package/dist/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.esm.js +0 -76
- package/dist/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.esm.js.map +0 -1
- package/dist/core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.esm.js +0 -234
- package/dist/core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.esm.js.map +0 -1
- package/dist/core-app-api/src/app/AppThemeProvider.esm.js +0 -60
- package/dist/core-app-api/src/app/AppThemeProvider.esm.js.map +0 -1
- package/dist/core-app-api/src/app/defaultConfigLoader.esm.js +0 -33
- package/dist/core-app-api/src/app/defaultConfigLoader.esm.js.map +0 -1
- package/dist/core-app-api/src/app/isProtectedApp.esm.js +0 -8
- package/dist/core-app-api/src/app/isProtectedApp.esm.js.map +0 -1
- package/dist/core-app-api/src/app/overrideBaseUrlConfigs.esm.js +0 -50
- package/dist/core-app-api/src/app/overrideBaseUrlConfigs.esm.js.map +0 -1
- package/dist/core-app-api/src/lib/subjects.esm.js +0 -69
- package/dist/core-app-api/src/lib/subjects.esm.js.map +0 -1
- package/dist/core-plugin-api/src/translation/TranslationRef.esm.js +0 -13
- package/dist/core-plugin-api/src/translation/TranslationRef.esm.js.map +0 -1
- package/dist/core-plugin-api/src/translation/TranslationResource.esm.js +0 -13
- package/dist/core-plugin-api/src/translation/TranslationResource.esm.js.map +0 -1
- package/dist/extensions/App.esm.js +0 -31
- package/dist/extensions/App.esm.js.map +0 -1
- package/dist/extensions/AppLayout.esm.js +0 -26
- package/dist/extensions/AppLayout.esm.js.map +0 -1
- package/dist/extensions/AppNav.esm.js +0 -66
- package/dist/extensions/AppNav.esm.js.map +0 -1
- package/dist/extensions/AppRoot.esm.js +0 -126
- package/dist/extensions/AppRoot.esm.js.map +0 -1
- package/dist/extensions/AppRoutes.esm.js +0 -39
- package/dist/extensions/AppRoutes.esm.js.map +0 -1
- package/dist/extensions/components.esm.js +0 -52
- package/dist/extensions/components.esm.js.map +0 -1
- package/dist/extensions/elements.esm.js +0 -32
- package/dist/extensions/elements.esm.js.map +0 -1
- package/dist/extensions/themes.esm.js +0 -33
- package/dist/extensions/themes.esm.js.map +0 -1
- package/dist/routing/RouteTracker.esm.js +0 -69
- package/dist/routing/RouteTracker.esm.js.map +0 -1
- package/dist/tree/createAppTree.esm.js +0 -21
- package/dist/tree/createAppTree.esm.js.map +0 -1
- package/dist/wiring/InternalAppContext.esm.js +0 -6
- package/dist/wiring/InternalAppContext.esm.js.map +0 -1
- package/dist/wiring/createApp.esm.js +0 -275
- package/dist/wiring/createApp.esm.js.map +0 -1
- package/dist/wiring/discovery.esm.js +0 -54
- package/dist/wiring/discovery.esm.js.map +0 -1
package/dist/core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.esm.js
DELETED
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
import { createInstance } from 'i18next';
|
|
2
|
-
import ObservableImpl from 'zen-observable';
|
|
3
|
-
import { toInternalTranslationResource } from '../../../../../core-plugin-api/src/translation/TranslationResource.esm.js';
|
|
4
|
-
import { toInternalTranslationRef } from '../../../../../core-plugin-api/src/translation/TranslationRef.esm.js';
|
|
5
|
-
import { DEFAULT_LANGUAGE } from '../AppLanguageApi/AppLanguageSelector.esm.js';
|
|
6
|
-
|
|
7
|
-
function removeNulls(messages) {
|
|
8
|
-
return Object.fromEntries(
|
|
9
|
-
Object.entries(messages).filter(
|
|
10
|
-
(e) => e[1] !== null
|
|
11
|
-
)
|
|
12
|
-
);
|
|
13
|
-
}
|
|
14
|
-
class ResourceLoader {
|
|
15
|
-
constructor(onLoad) {
|
|
16
|
-
this.onLoad = onLoad;
|
|
17
|
-
}
|
|
18
|
-
/** Loaded resources by loader key */
|
|
19
|
-
#loaded = /* @__PURE__ */ new Set();
|
|
20
|
-
/** Resource loading promises by loader key */
|
|
21
|
-
#loading = /* @__PURE__ */ new Map();
|
|
22
|
-
/** Loaders for each resource language */
|
|
23
|
-
#loaders = /* @__PURE__ */ new Map();
|
|
24
|
-
addTranslationResource(resource) {
|
|
25
|
-
const internalResource = toInternalTranslationResource(resource);
|
|
26
|
-
for (const entry of internalResource.resources) {
|
|
27
|
-
const key = this.#getLoaderKey(entry.language, internalResource.id);
|
|
28
|
-
if (!this.#loaders.has(key)) {
|
|
29
|
-
this.#loaders.set(key, entry.loader);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
#getLoaderKey(language, namespace) {
|
|
34
|
-
return `${language}/${namespace}`;
|
|
35
|
-
}
|
|
36
|
-
needsLoading(language, namespace) {
|
|
37
|
-
const key = this.#getLoaderKey(language, namespace);
|
|
38
|
-
const loader = this.#loaders.get(key);
|
|
39
|
-
if (!loader) {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
return !this.#loaded.has(key);
|
|
43
|
-
}
|
|
44
|
-
async load(language, namespace) {
|
|
45
|
-
const key = this.#getLoaderKey(language, namespace);
|
|
46
|
-
const loader = this.#loaders.get(key);
|
|
47
|
-
if (!loader) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
if (this.#loaded.has(key)) {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
const loading = this.#loading.get(key);
|
|
54
|
-
if (loading) {
|
|
55
|
-
await loading;
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
const load = loader().then(
|
|
59
|
-
(result) => {
|
|
60
|
-
this.onLoad({ language, namespace, messages: result.messages });
|
|
61
|
-
this.#loaded.add(key);
|
|
62
|
-
},
|
|
63
|
-
(error) => {
|
|
64
|
-
this.#loaded.add(key);
|
|
65
|
-
throw error;
|
|
66
|
-
}
|
|
67
|
-
);
|
|
68
|
-
this.#loading.set(key, load);
|
|
69
|
-
await load;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
class I18nextTranslationApi {
|
|
73
|
-
static create(options) {
|
|
74
|
-
const { languages } = options.languageApi.getAvailableLanguages();
|
|
75
|
-
const i18n = createInstance({
|
|
76
|
-
fallbackLng: DEFAULT_LANGUAGE,
|
|
77
|
-
supportedLngs: languages,
|
|
78
|
-
interpolation: {
|
|
79
|
-
escapeValue: false
|
|
80
|
-
},
|
|
81
|
-
ns: [],
|
|
82
|
-
defaultNS: false,
|
|
83
|
-
fallbackNS: false,
|
|
84
|
-
// Disable resource loading on init, meaning i18n will be ready to use immediately
|
|
85
|
-
initImmediate: false
|
|
86
|
-
});
|
|
87
|
-
i18n.init();
|
|
88
|
-
if (!i18n.isInitialized) {
|
|
89
|
-
throw new Error("i18next was unexpectedly not initialized");
|
|
90
|
-
}
|
|
91
|
-
const { language: initialLanguage } = options.languageApi.getLanguage();
|
|
92
|
-
if (initialLanguage !== DEFAULT_LANGUAGE) {
|
|
93
|
-
i18n.changeLanguage(initialLanguage);
|
|
94
|
-
}
|
|
95
|
-
const loader = new ResourceLoader((loaded) => {
|
|
96
|
-
i18n.addResourceBundle(
|
|
97
|
-
loaded.language,
|
|
98
|
-
loaded.namespace,
|
|
99
|
-
removeNulls(loaded.messages),
|
|
100
|
-
false,
|
|
101
|
-
// do not merge with existing translations
|
|
102
|
-
true
|
|
103
|
-
// overwrite translations
|
|
104
|
-
);
|
|
105
|
-
});
|
|
106
|
-
const resources = options?.resources || [];
|
|
107
|
-
for (let i = resources.length - 1; i >= 0; i--) {
|
|
108
|
-
const resource = resources[i];
|
|
109
|
-
if (resource.$$type === "@backstage/TranslationResource") {
|
|
110
|
-
loader.addTranslationResource(resource);
|
|
111
|
-
} else if (resource.$$type === "@backstage/TranslationMessages") {
|
|
112
|
-
i18n.addResourceBundle(
|
|
113
|
-
DEFAULT_LANGUAGE,
|
|
114
|
-
resource.id,
|
|
115
|
-
removeNulls(resource.messages),
|
|
116
|
-
true,
|
|
117
|
-
// merge with existing translations
|
|
118
|
-
false
|
|
119
|
-
// do not overwrite translations
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
const instance = new I18nextTranslationApi(
|
|
124
|
-
i18n,
|
|
125
|
-
loader,
|
|
126
|
-
options.languageApi.getLanguage().language
|
|
127
|
-
);
|
|
128
|
-
options.languageApi.language$().subscribe(({ language }) => {
|
|
129
|
-
instance.#changeLanguage(language);
|
|
130
|
-
});
|
|
131
|
-
return instance;
|
|
132
|
-
}
|
|
133
|
-
#i18n;
|
|
134
|
-
#loader;
|
|
135
|
-
#language;
|
|
136
|
-
/** Keep track of which refs we have registered default resources for */
|
|
137
|
-
#registeredRefs = /* @__PURE__ */ new Set();
|
|
138
|
-
/** Notify observers when language changes */
|
|
139
|
-
#languageChangeListeners = /* @__PURE__ */ new Set();
|
|
140
|
-
constructor(i18n, loader, language) {
|
|
141
|
-
this.#i18n = i18n;
|
|
142
|
-
this.#loader = loader;
|
|
143
|
-
this.#language = language;
|
|
144
|
-
}
|
|
145
|
-
getTranslation(translationRef) {
|
|
146
|
-
const internalRef = toInternalTranslationRef(translationRef);
|
|
147
|
-
this.#registerDefaults(internalRef);
|
|
148
|
-
return this.#createSnapshot(internalRef);
|
|
149
|
-
}
|
|
150
|
-
translation$(translationRef) {
|
|
151
|
-
const internalRef = toInternalTranslationRef(translationRef);
|
|
152
|
-
this.#registerDefaults(internalRef);
|
|
153
|
-
return new ObservableImpl((subscriber) => {
|
|
154
|
-
let loadTicket = {};
|
|
155
|
-
const loadResource = () => {
|
|
156
|
-
loadTicket = {};
|
|
157
|
-
const ticket = loadTicket;
|
|
158
|
-
this.#loader.load(this.#language, internalRef.id).then(
|
|
159
|
-
() => {
|
|
160
|
-
if (ticket === loadTicket) {
|
|
161
|
-
const snapshot = this.#createSnapshot(internalRef);
|
|
162
|
-
if (snapshot.ready) {
|
|
163
|
-
subscriber.next(snapshot);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
},
|
|
167
|
-
(error) => {
|
|
168
|
-
if (ticket === loadTicket) {
|
|
169
|
-
subscriber.error(Array.isArray(error) ? error[0] : error);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
);
|
|
173
|
-
};
|
|
174
|
-
const onChange = () => {
|
|
175
|
-
const snapshot = this.#createSnapshot(internalRef);
|
|
176
|
-
if (snapshot.ready) {
|
|
177
|
-
subscriber.next(snapshot);
|
|
178
|
-
} else {
|
|
179
|
-
loadResource();
|
|
180
|
-
}
|
|
181
|
-
};
|
|
182
|
-
if (this.#loader.needsLoading(this.#language, internalRef.id)) {
|
|
183
|
-
loadResource();
|
|
184
|
-
}
|
|
185
|
-
this.#languageChangeListeners.add(onChange);
|
|
186
|
-
return () => {
|
|
187
|
-
this.#languageChangeListeners.delete(onChange);
|
|
188
|
-
};
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
#changeLanguage(language) {
|
|
192
|
-
if (this.#language !== language) {
|
|
193
|
-
this.#language = language;
|
|
194
|
-
this.#i18n.changeLanguage(language);
|
|
195
|
-
this.#languageChangeListeners.forEach((listener) => listener());
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
#createSnapshot(internalRef) {
|
|
199
|
-
if (this.#loader.needsLoading(this.#language, internalRef.id)) {
|
|
200
|
-
return { ready: false };
|
|
201
|
-
}
|
|
202
|
-
const t = this.#i18n.getFixedT(
|
|
203
|
-
null,
|
|
204
|
-
internalRef.id
|
|
205
|
-
);
|
|
206
|
-
return {
|
|
207
|
-
ready: true,
|
|
208
|
-
t
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
#registerDefaults(internalRef) {
|
|
212
|
-
if (this.#registeredRefs.has(internalRef.id)) {
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
this.#registeredRefs.add(internalRef.id);
|
|
216
|
-
const defaultMessages = internalRef.getDefaultMessages();
|
|
217
|
-
this.#i18n.addResourceBundle(
|
|
218
|
-
DEFAULT_LANGUAGE,
|
|
219
|
-
internalRef.id,
|
|
220
|
-
defaultMessages,
|
|
221
|
-
true,
|
|
222
|
-
// merge with existing translations
|
|
223
|
-
false
|
|
224
|
-
// do not overwrite translations
|
|
225
|
-
);
|
|
226
|
-
const defaultResource = internalRef.getDefaultResource();
|
|
227
|
-
if (defaultResource) {
|
|
228
|
-
this.#loader.addTranslationResource(defaultResource);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export { I18nextTranslationApi };
|
|
234
|
-
//# sourceMappingURL=I18nextTranslationApi.esm.js.map
|
package/dist/core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.esm.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"I18nextTranslationApi.esm.js","sources":["../../../../../../../core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AppLanguageApi,\n TranslationApi,\n TranslationFunction,\n TranslationMessages,\n TranslationRef,\n TranslationResource,\n TranslationSnapshot,\n} from '@backstage/core-plugin-api/alpha';\nimport { createInstance as createI18n, type i18n as I18n } from 'i18next';\nimport ObservableImpl from 'zen-observable';\n\n// Internal import to avoid code duplication, this will lead to duplication in build output\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport {\n toInternalTranslationResource,\n InternalTranslationResourceLoader,\n} from '../../../../../core-plugin-api/src/translation/TranslationResource';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport {\n toInternalTranslationRef,\n InternalTranslationRef,\n} from '../../../../../core-plugin-api/src/translation/TranslationRef';\nimport { Observable } from '@backstage/types';\nimport { DEFAULT_LANGUAGE } from '../AppLanguageApi/AppLanguageSelector';\n\n/** @alpha */\nexport interface I18nextTranslationApiOptions {\n languageApi: AppLanguageApi;\n resources?: Array<TranslationMessages | TranslationResource>;\n}\n\nfunction removeNulls(\n messages: Record<string, string | null>,\n): Record<string, string> {\n return Object.fromEntries(\n Object.entries(messages).filter(\n (e): e is [string, string] => e[1] !== null,\n ),\n );\n}\n\n/**\n * The built-in i18next backend loading logic doesn't handle on the fly switches\n * of language very well. It gets a bit confused about whether resources are actually\n * loaded or not, so instead we implement our own resource loader.\n */\nclass ResourceLoader {\n /** Loaded resources by loader key */\n #loaded = new Set<string>();\n /** Resource loading promises by loader key */\n #loading = new Map<string, Promise<void>>();\n /** Loaders for each resource language */\n #loaders = new Map<string, InternalTranslationResourceLoader>();\n\n constructor(\n private readonly onLoad: (loaded: {\n language: string;\n namespace: string;\n messages: Record<string, string | null>;\n }) => void,\n ) {}\n\n addTranslationResource(resource: TranslationResource) {\n const internalResource = toInternalTranslationResource(resource);\n for (const entry of internalResource.resources) {\n const key = this.#getLoaderKey(entry.language, internalResource.id);\n\n // First loader to register wins, this means that resources registered in the app\n // have priority over default resource from translation refs\n if (!this.#loaders.has(key)) {\n this.#loaders.set(key, entry.loader);\n }\n }\n }\n\n #getLoaderKey(language: string, namespace: string) {\n return `${language}/${namespace}`;\n }\n\n needsLoading(language: string, namespace: string) {\n const key = this.#getLoaderKey(language, namespace);\n const loader = this.#loaders.get(key);\n if (!loader) {\n return false;\n }\n\n return !this.#loaded.has(key);\n }\n\n async load(language: string, namespace: string): Promise<void> {\n const key = this.#getLoaderKey(language, namespace);\n\n const loader = this.#loaders.get(key);\n if (!loader) {\n return;\n }\n\n if (this.#loaded.has(key)) {\n return;\n }\n\n const loading = this.#loading.get(key);\n if (loading) {\n await loading;\n return;\n }\n\n const load = loader().then(\n result => {\n this.onLoad({ language, namespace, messages: result.messages });\n this.#loaded.add(key);\n },\n error => {\n this.#loaded.add(key); // Do not try to load failed resources again\n throw error;\n },\n );\n this.#loading.set(key, load);\n await load;\n }\n}\n\n/** @alpha */\nexport class I18nextTranslationApi implements TranslationApi {\n static create(options: I18nextTranslationApiOptions) {\n const { languages } = options.languageApi.getAvailableLanguages();\n\n const i18n = createI18n({\n fallbackLng: DEFAULT_LANGUAGE,\n supportedLngs: languages,\n interpolation: {\n escapeValue: false,\n },\n ns: [],\n defaultNS: false,\n fallbackNS: false,\n\n // Disable resource loading on init, meaning i18n will be ready to use immediately\n initImmediate: false,\n });\n\n i18n.init();\n if (!i18n.isInitialized) {\n throw new Error('i18next was unexpectedly not initialized');\n }\n\n const { language: initialLanguage } = options.languageApi.getLanguage();\n if (initialLanguage !== DEFAULT_LANGUAGE) {\n i18n.changeLanguage(initialLanguage);\n }\n\n const loader = new ResourceLoader(loaded => {\n i18n.addResourceBundle(\n loaded.language,\n loaded.namespace,\n removeNulls(loaded.messages),\n false, // do not merge with existing translations\n true, // overwrite translations\n );\n });\n\n const resources = options?.resources || [];\n // Iterate in reverse, giving higher priority to resources registered later\n for (let i = resources.length - 1; i >= 0; i--) {\n const resource = resources[i];\n if (resource.$$type === '@backstage/TranslationResource') {\n loader.addTranslationResource(resource);\n } else if (resource.$$type === '@backstage/TranslationMessages') {\n // Overrides for default messages, created with createTranslationMessages and installed via app\n i18n.addResourceBundle(\n DEFAULT_LANGUAGE,\n resource.id,\n removeNulls(resource.messages),\n true, // merge with existing translations\n false, // do not overwrite translations\n );\n }\n }\n\n const instance = new I18nextTranslationApi(\n i18n,\n loader,\n options.languageApi.getLanguage().language,\n );\n\n options.languageApi.language$().subscribe(({ language }) => {\n instance.#changeLanguage(language);\n });\n\n return instance;\n }\n\n #i18n: I18n;\n #loader: ResourceLoader;\n #language: string;\n\n /** Keep track of which refs we have registered default resources for */\n #registeredRefs = new Set<string>();\n /** Notify observers when language changes */\n #languageChangeListeners = new Set<() => void>();\n\n private constructor(i18n: I18n, loader: ResourceLoader, language: string) {\n this.#i18n = i18n;\n this.#loader = loader;\n this.#language = language;\n }\n\n getTranslation<TMessages extends { [key in string]: string }>(\n translationRef: TranslationRef<string, TMessages>,\n ): TranslationSnapshot<TMessages> {\n const internalRef = toInternalTranslationRef(translationRef);\n\n this.#registerDefaults(internalRef);\n\n return this.#createSnapshot(internalRef);\n }\n\n translation$<TMessages extends { [key in string]: string }>(\n translationRef: TranslationRef<string, TMessages>,\n ): Observable<TranslationSnapshot<TMessages>> {\n const internalRef = toInternalTranslationRef(translationRef);\n\n this.#registerDefaults(internalRef);\n\n return new ObservableImpl<TranslationSnapshot<TMessages>>(subscriber => {\n let loadTicket = {}; // To check for stale loads\n\n const loadResource = () => {\n loadTicket = {};\n const ticket = loadTicket;\n this.#loader.load(this.#language, internalRef.id).then(\n () => {\n if (ticket === loadTicket) {\n const snapshot = this.#createSnapshot(internalRef);\n if (snapshot.ready) {\n subscriber.next(snapshot);\n }\n }\n },\n error => {\n if (ticket === loadTicket) {\n subscriber.error(Array.isArray(error) ? error[0] : error);\n }\n },\n );\n };\n\n const onChange = () => {\n const snapshot = this.#createSnapshot(internalRef);\n if (snapshot.ready) {\n subscriber.next(snapshot);\n } else {\n loadResource();\n }\n };\n\n if (this.#loader.needsLoading(this.#language, internalRef.id)) {\n loadResource();\n }\n\n this.#languageChangeListeners.add(onChange);\n return () => {\n this.#languageChangeListeners.delete(onChange);\n };\n });\n }\n\n #changeLanguage(language: string): void {\n if (this.#language !== language) {\n this.#language = language;\n this.#i18n.changeLanguage(language);\n this.#languageChangeListeners.forEach(listener => listener());\n }\n }\n\n #createSnapshot<TMessages extends { [key in string]: string }>(\n internalRef: InternalTranslationRef<string, TMessages>,\n ): TranslationSnapshot<TMessages> {\n if (this.#loader.needsLoading(this.#language, internalRef.id)) {\n return { ready: false };\n }\n\n const t = this.#i18n.getFixedT(\n null,\n internalRef.id,\n ) as TranslationFunction<TMessages>;\n\n return {\n ready: true,\n t,\n };\n }\n\n #registerDefaults(internalRef: InternalTranslationRef): void {\n if (this.#registeredRefs.has(internalRef.id)) {\n return;\n }\n this.#registeredRefs.add(internalRef.id);\n\n const defaultMessages = internalRef.getDefaultMessages();\n this.#i18n.addResourceBundle(\n DEFAULT_LANGUAGE,\n internalRef.id,\n defaultMessages,\n true, // merge with existing translations\n false, // do not overwrite translations\n );\n\n const defaultResource = internalRef.getDefaultResource();\n if (defaultResource) {\n this.#loader.addTranslationResource(defaultResource);\n }\n }\n}\n"],"names":["createI18n"],"mappings":"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"}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import React, { useMemo, useState, useEffect } from 'react';
|
|
2
|
-
import { useApi, appThemeApiRef } from '@backstage/core-plugin-api';
|
|
3
|
-
import useObservable from 'react-use/esm/useObservable';
|
|
4
|
-
|
|
5
|
-
function resolveTheme(themeId, shouldPreferDark, themes) {
|
|
6
|
-
if (themeId !== void 0) {
|
|
7
|
-
const selectedTheme = themes.find((theme) => theme.id === themeId);
|
|
8
|
-
if (selectedTheme) {
|
|
9
|
-
return selectedTheme;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
if (shouldPreferDark) {
|
|
13
|
-
const darkTheme = themes.find((theme) => theme.variant === "dark");
|
|
14
|
-
if (darkTheme) {
|
|
15
|
-
return darkTheme;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
const lightTheme = themes.find((theme) => theme.variant === "light");
|
|
19
|
-
if (lightTheme) {
|
|
20
|
-
return lightTheme;
|
|
21
|
-
}
|
|
22
|
-
return themes[0];
|
|
23
|
-
}
|
|
24
|
-
const useShouldPreferDarkTheme = () => {
|
|
25
|
-
const mediaQuery = useMemo(
|
|
26
|
-
() => window.matchMedia("(prefers-color-scheme: dark)"),
|
|
27
|
-
[]
|
|
28
|
-
);
|
|
29
|
-
const [shouldPreferDark, setPrefersDark] = useState(mediaQuery.matches);
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
const listener = (event) => {
|
|
32
|
-
setPrefersDark(event.matches);
|
|
33
|
-
};
|
|
34
|
-
mediaQuery.addListener(listener);
|
|
35
|
-
return () => {
|
|
36
|
-
mediaQuery.removeListener(listener);
|
|
37
|
-
};
|
|
38
|
-
}, [mediaQuery]);
|
|
39
|
-
return shouldPreferDark;
|
|
40
|
-
};
|
|
41
|
-
function AppThemeProvider({ children }) {
|
|
42
|
-
const appThemeApi = useApi(appThemeApiRef);
|
|
43
|
-
const themeId = useObservable(
|
|
44
|
-
appThemeApi.activeThemeId$(),
|
|
45
|
-
appThemeApi.getActiveThemeId()
|
|
46
|
-
);
|
|
47
|
-
const shouldPreferDark = Boolean(window.matchMedia) ? useShouldPreferDarkTheme() : false;
|
|
48
|
-
const appTheme = resolveTheme(
|
|
49
|
-
themeId,
|
|
50
|
-
shouldPreferDark,
|
|
51
|
-
appThemeApi.getInstalledThemes()
|
|
52
|
-
);
|
|
53
|
-
if (!appTheme) {
|
|
54
|
-
throw new Error("App has no themes");
|
|
55
|
-
}
|
|
56
|
-
return /* @__PURE__ */ React.createElement(appTheme.Provider, { children });
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export { AppThemeProvider };
|
|
60
|
-
//# sourceMappingURL=AppThemeProvider.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AppThemeProvider.esm.js","sources":["../../../../../core-app-api/src/app/AppThemeProvider.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useMemo, useEffect, useState, PropsWithChildren } from 'react';\nimport { useApi, appThemeApiRef, AppTheme } from '@backstage/core-plugin-api';\nimport useObservable from 'react-use/esm/useObservable';\n\n// This tries to find the most accurate match, but also falls back to less\n// accurate results in order to avoid errors.\nfunction resolveTheme(\n themeId: string | undefined,\n shouldPreferDark: boolean,\n themes: AppTheme[],\n) {\n if (themeId !== undefined) {\n const selectedTheme = themes.find(theme => theme.id === themeId);\n if (selectedTheme) {\n return selectedTheme;\n }\n }\n\n if (shouldPreferDark) {\n const darkTheme = themes.find(theme => theme.variant === 'dark');\n if (darkTheme) {\n return darkTheme;\n }\n }\n\n const lightTheme = themes.find(theme => theme.variant === 'light');\n if (lightTheme) {\n return lightTheme;\n }\n\n return themes[0];\n}\n\nconst useShouldPreferDarkTheme = () => {\n const mediaQuery = useMemo(\n () => window.matchMedia('(prefers-color-scheme: dark)'),\n [],\n );\n const [shouldPreferDark, setPrefersDark] = useState(mediaQuery.matches);\n\n useEffect(() => {\n const listener = (event: MediaQueryListEvent) => {\n setPrefersDark(event.matches);\n };\n mediaQuery.addListener(listener);\n return () => {\n mediaQuery.removeListener(listener);\n };\n }, [mediaQuery]);\n\n return shouldPreferDark;\n};\n\nexport function AppThemeProvider({ children }: PropsWithChildren<{}>) {\n const appThemeApi = useApi(appThemeApiRef);\n const themeId = useObservable(\n appThemeApi.activeThemeId$(),\n appThemeApi.getActiveThemeId(),\n );\n\n // Browser feature detection won't change over time, so ignore lint rule\n const shouldPreferDark = Boolean(window.matchMedia)\n ? useShouldPreferDarkTheme() // eslint-disable-line react-hooks/rules-of-hooks\n : false;\n\n const appTheme = resolveTheme(\n themeId,\n shouldPreferDark,\n appThemeApi.getInstalledThemes(),\n );\n if (!appTheme) {\n throw new Error('App has no themes');\n }\n\n return <appTheme.Provider children={children} />;\n}\n"],"names":[],"mappings":";;;;AAsBA,SAAS,YAAA,CACP,OACA,EAAA,gBAAA,EACA,MACA,EAAA;AACA,EAAA,IAAI,YAAY,KAAW,CAAA,EAAA;AACzB,IAAA,MAAM,gBAAgB,MAAO,CAAA,IAAA,CAAK,CAAS,KAAA,KAAA,KAAA,CAAM,OAAO,OAAO,CAAA,CAAA;AAC/D,IAAA,IAAI,aAAe,EAAA;AACjB,MAAO,OAAA,aAAA,CAAA;AAAA,KACT;AAAA,GACF;AAEA,EAAA,IAAI,gBAAkB,EAAA;AACpB,IAAA,MAAM,YAAY,MAAO,CAAA,IAAA,CAAK,CAAS,KAAA,KAAA,KAAA,CAAM,YAAY,MAAM,CAAA,CAAA;AAC/D,IAAA,IAAI,SAAW,EAAA;AACb,MAAO,OAAA,SAAA,CAAA;AAAA,KACT;AAAA,GACF;AAEA,EAAA,MAAM,aAAa,MAAO,CAAA,IAAA,CAAK,CAAS,KAAA,KAAA,KAAA,CAAM,YAAY,OAAO,CAAA,CAAA;AACjE,EAAA,IAAI,UAAY,EAAA;AACd,IAAO,OAAA,UAAA,CAAA;AAAA,GACT;AAEA,EAAA,OAAO,OAAO,CAAC,CAAA,CAAA;AACjB,CAAA;AAEA,MAAM,2BAA2B,MAAM;AACrC,EAAA,MAAM,UAAa,GAAA,OAAA;AAAA,IACjB,MAAM,MAAO,CAAA,UAAA,CAAW,8BAA8B,CAAA;AAAA,IACtD,EAAC;AAAA,GACH,CAAA;AACA,EAAA,MAAM,CAAC,gBAAkB,EAAA,cAAc,CAAI,GAAA,QAAA,CAAS,WAAW,OAAO,CAAA,CAAA;AAEtE,EAAA,SAAA,CAAU,MAAM;AACd,IAAM,MAAA,QAAA,GAAW,CAAC,KAA+B,KAAA;AAC/C,MAAA,cAAA,CAAe,MAAM,OAAO,CAAA,CAAA;AAAA,KAC9B,CAAA;AACA,IAAA,UAAA,CAAW,YAAY,QAAQ,CAAA,CAAA;AAC/B,IAAA,OAAO,MAAM;AACX,MAAA,UAAA,CAAW,eAAe,QAAQ,CAAA,CAAA;AAAA,KACpC,CAAA;AAAA,GACF,EAAG,CAAC,UAAU,CAAC,CAAA,CAAA;AAEf,EAAO,OAAA,gBAAA,CAAA;AACT,CAAA,CAAA;AAEgB,SAAA,gBAAA,CAAiB,EAAE,QAAA,EAAmC,EAAA;AACpE,EAAM,MAAA,WAAA,GAAc,OAAO,cAAc,CAAA,CAAA;AACzC,EAAA,MAAM,OAAU,GAAA,aAAA;AAAA,IACd,YAAY,cAAe,EAAA;AAAA,IAC3B,YAAY,gBAAiB,EAAA;AAAA,GAC/B,CAAA;AAGA,EAAA,MAAM,mBAAmB,OAAQ,CAAA,MAAA,CAAO,UAAU,CAAA,GAC9C,0BACA,GAAA,KAAA,CAAA;AAEJ,EAAA,MAAM,QAAW,GAAA,YAAA;AAAA,IACf,OAAA;AAAA,IACA,gBAAA;AAAA,IACA,YAAY,kBAAmB,EAAA;AAAA,GACjC,CAAA;AACA,EAAA,IAAI,CAAC,QAAU,EAAA;AACb,IAAM,MAAA,IAAI,MAAM,mBAAmB,CAAA,CAAA;AAAA,GACrC;AAEA,EAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,QAAA,CAAS,QAAT,EAAA,EAAkB,QAAoB,EAAA,CAAA,CAAA;AAChD;;;;"}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
function defaultConfigLoaderSync(runtimeConfigJson = "__APP_INJECTED_RUNTIME_CONFIG__") {
|
|
2
|
-
const appConfig = process.env.APP_CONFIG;
|
|
3
|
-
if (!appConfig) {
|
|
4
|
-
throw new Error("No static configuration provided");
|
|
5
|
-
}
|
|
6
|
-
if (!Array.isArray(appConfig)) {
|
|
7
|
-
throw new Error("Static configuration has invalid format");
|
|
8
|
-
}
|
|
9
|
-
const configs = appConfig.slice();
|
|
10
|
-
if (runtimeConfigJson !== "__app_injected_runtime_config__".toLocaleUpperCase("en-US")) {
|
|
11
|
-
try {
|
|
12
|
-
const data = JSON.parse(runtimeConfigJson);
|
|
13
|
-
if (Array.isArray(data)) {
|
|
14
|
-
configs.push(...data);
|
|
15
|
-
} else {
|
|
16
|
-
configs.push({ data, context: "env" });
|
|
17
|
-
}
|
|
18
|
-
} catch (error) {
|
|
19
|
-
throw new Error(`Failed to load runtime configuration, ${error}`);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
const windowAppConfig = window.__APP_CONFIG__;
|
|
23
|
-
if (windowAppConfig) {
|
|
24
|
-
configs.push({
|
|
25
|
-
context: "window",
|
|
26
|
-
data: windowAppConfig
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
return configs;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export { defaultConfigLoaderSync };
|
|
33
|
-
//# sourceMappingURL=defaultConfigLoader.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"defaultConfigLoader.esm.js","sources":["../../../../../core-app-api/src/app/defaultConfigLoader.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AppConfig } from '@backstage/config';\nimport { JsonObject } from '@backstage/types';\nimport { AppConfigLoader } from './types';\n\n/**\n * The default config loader, which expects that config is available at compile-time\n * in `process.env.APP_CONFIG`. APP_CONFIG should be an array of config objects as\n * returned by the config loader.\n *\n * It will also load runtime config from the __APP_INJECTED_RUNTIME_CONFIG__ string,\n * which can be rewritten at runtime to contain an additional JSON config object.\n * If runtime config is present, it will be placed first in the config array, overriding\n * other config values.\n *\n * @public\n */\nexport const defaultConfigLoader: AppConfigLoader = async () =>\n defaultConfigLoaderSync();\n\n/** @internal */\nexport function defaultConfigLoaderSync(\n // This string may be replaced at runtime to provide additional config.\n // It should be replaced by a JSON-serialized config object.\n // It's a param so we can test it, but at runtime this will always fall back to default.\n runtimeConfigJson: string = '__APP_INJECTED_RUNTIME_CONFIG__',\n) {\n const appConfig = process.env.APP_CONFIG;\n if (!appConfig) {\n throw new Error('No static configuration provided');\n }\n if (!Array.isArray(appConfig)) {\n throw new Error('Static configuration has invalid format');\n }\n const configs = appConfig.slice() as unknown as AppConfig[];\n\n // Avoiding this string also being replaced at runtime\n if (\n runtimeConfigJson !==\n '__app_injected_runtime_config__'.toLocaleUpperCase('en-US')\n ) {\n try {\n const data = JSON.parse(runtimeConfigJson) as JsonObject;\n if (Array.isArray(data)) {\n configs.push(...data);\n } else {\n configs.push({ data, context: 'env' });\n }\n } catch (error) {\n throw new Error(`Failed to load runtime configuration, ${error}`);\n }\n }\n\n const windowAppConfig = (window as any).__APP_CONFIG__;\n if (windowAppConfig) {\n configs.push({\n context: 'window',\n data: windowAppConfig,\n });\n }\n return configs;\n}\n"],"names":[],"mappings":"AAoCgB,SAAA,uBAAA,CAId,oBAA4B,iCAC5B,EAAA;AACA,EAAM,MAAA,SAAA,GAAY,QAAQ,GAAI,CAAA,UAAA,CAAA;AAC9B,EAAA,IAAI,CAAC,SAAW,EAAA;AACd,IAAM,MAAA,IAAI,MAAM,kCAAkC,CAAA,CAAA;AAAA,GACpD;AACA,EAAA,IAAI,CAAC,KAAA,CAAM,OAAQ,CAAA,SAAS,CAAG,EAAA;AAC7B,IAAM,MAAA,IAAI,MAAM,yCAAyC,CAAA,CAAA;AAAA,GAC3D;AACA,EAAM,MAAA,OAAA,GAAU,UAAU,KAAM,EAAA,CAAA;AAGhC,EAAA,IACE,iBACA,KAAA,iCAAA,CAAkC,iBAAkB,CAAA,OAAO,CAC3D,EAAA;AACA,IAAI,IAAA;AACF,MAAM,MAAA,IAAA,GAAO,IAAK,CAAA,KAAA,CAAM,iBAAiB,CAAA,CAAA;AACzC,MAAI,IAAA,KAAA,CAAM,OAAQ,CAAA,IAAI,CAAG,EAAA;AACvB,QAAQ,OAAA,CAAA,IAAA,CAAK,GAAG,IAAI,CAAA,CAAA;AAAA,OACf,MAAA;AACL,QAAA,OAAA,CAAQ,IAAK,CAAA,EAAE,IAAM,EAAA,OAAA,EAAS,OAAO,CAAA,CAAA;AAAA,OACvC;AAAA,aACO,KAAO,EAAA;AACd,MAAA,MAAM,IAAI,KAAA,CAAM,CAAyC,sCAAA,EAAA,KAAK,CAAE,CAAA,CAAA,CAAA;AAAA,KAClE;AAAA,GACF;AAEA,EAAA,MAAM,kBAAmB,MAAe,CAAA,cAAA,CAAA;AACxC,EAAA,IAAI,eAAiB,EAAA;AACnB,IAAA,OAAA,CAAQ,IAAK,CAAA;AAAA,MACX,OAAS,EAAA,QAAA;AAAA,MACT,IAAM,EAAA,eAAA;AAAA,KACP,CAAA,CAAA;AAAA,GACH;AACA,EAAO,OAAA,OAAA,CAAA;AACT;;;;"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
function isProtectedApp() {
|
|
2
|
-
const element = document.querySelector('meta[name="backstage-app-mode"]');
|
|
3
|
-
const appMode = element?.getAttribute("content") ?? "public";
|
|
4
|
-
return appMode === "protected";
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export { isProtectedApp };
|
|
8
|
-
//# sourceMappingURL=isProtectedApp.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"isProtectedApp.esm.js","sources":["../../../../../core-app-api/src/app/isProtectedApp.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport function isProtectedApp() {\n const element = document.querySelector('meta[name=\"backstage-app-mode\"]');\n const appMode = element?.getAttribute('content') ?? 'public';\n return appMode === 'protected';\n}\n"],"names":[],"mappings":"AAgBO,SAAS,cAAiB,GAAA;AAC/B,EAAM,MAAA,OAAA,GAAU,QAAS,CAAA,aAAA,CAAc,iCAAiC,CAAA,CAAA;AACxE,EAAA,MAAM,OAAU,GAAA,OAAA,EAAS,YAAa,CAAA,SAAS,CAAK,IAAA,QAAA,CAAA;AACpD,EAAA,OAAO,OAAY,KAAA,WAAA,CAAA;AACrB;;;;"}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { ConfigReader } from '@backstage/config';
|
|
2
|
-
|
|
3
|
-
function createLocalBaseUrl(fullUrl) {
|
|
4
|
-
const url = new URL(fullUrl);
|
|
5
|
-
url.protocol = document.location.protocol;
|
|
6
|
-
url.hostname = document.location.hostname;
|
|
7
|
-
url.port = document.location.port;
|
|
8
|
-
return url.toString().replace(/\/$/, "");
|
|
9
|
-
}
|
|
10
|
-
function overrideBaseUrlConfigs(inputConfigs) {
|
|
11
|
-
const urlConfigReader = ConfigReader.fromConfigs(inputConfigs);
|
|
12
|
-
const appBaseUrl = urlConfigReader.getOptionalString("app.baseUrl");
|
|
13
|
-
const backendBaseUrl = urlConfigReader.getOptionalString("backend.baseUrl");
|
|
14
|
-
let configs = inputConfigs;
|
|
15
|
-
let newBackendBaseUrl = void 0;
|
|
16
|
-
let newAppBaseUrl = void 0;
|
|
17
|
-
if (appBaseUrl && backendBaseUrl) {
|
|
18
|
-
const appOrigin = new URL(appBaseUrl).origin;
|
|
19
|
-
const backendOrigin = new URL(backendBaseUrl).origin;
|
|
20
|
-
if (appOrigin === backendOrigin) {
|
|
21
|
-
const maybeNewBackendBaseUrl = createLocalBaseUrl(backendBaseUrl);
|
|
22
|
-
if (backendBaseUrl !== maybeNewBackendBaseUrl) {
|
|
23
|
-
newBackendBaseUrl = maybeNewBackendBaseUrl;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
if (appBaseUrl) {
|
|
28
|
-
const maybeNewAppBaseUrl = createLocalBaseUrl(appBaseUrl);
|
|
29
|
-
if (appBaseUrl !== maybeNewAppBaseUrl) {
|
|
30
|
-
newAppBaseUrl = maybeNewAppBaseUrl;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
if (newAppBaseUrl || newBackendBaseUrl) {
|
|
34
|
-
configs = configs.concat({
|
|
35
|
-
data: {
|
|
36
|
-
app: newAppBaseUrl && {
|
|
37
|
-
baseUrl: newAppBaseUrl
|
|
38
|
-
},
|
|
39
|
-
backend: newBackendBaseUrl && {
|
|
40
|
-
baseUrl: newBackendBaseUrl
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
context: "relative-resolver"
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
return configs;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export { overrideBaseUrlConfigs };
|
|
50
|
-
//# sourceMappingURL=overrideBaseUrlConfigs.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"overrideBaseUrlConfigs.esm.js","sources":["../../../../../core-app-api/src/app/overrideBaseUrlConfigs.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 { AppConfig, ConfigReader } from '@backstage/config';\n\n/**\n * Creates a base URL that uses to the current document origin.\n */\nfunction createLocalBaseUrl(fullUrl: string): string {\n const url = new URL(fullUrl);\n url.protocol = document.location.protocol;\n url.hostname = document.location.hostname;\n url.port = document.location.port;\n return url.toString().replace(/\\/$/, '');\n}\n\n/**\n * If we are able to override the app and backend base URLs to values that\n * match the origin of the current location, then this function returns a\n * new array of app configs that contain the overrides.\n *\n * @internal\n */\nexport function overrideBaseUrlConfigs(inputConfigs: AppConfig[]): AppConfig[] {\n const urlConfigReader = ConfigReader.fromConfigs(inputConfigs);\n\n // In tests we may not have `app.baseUrl` or `backend.baseUrl`, to keep them optional\n const appBaseUrl = urlConfigReader.getOptionalString('app.baseUrl');\n const backendBaseUrl = urlConfigReader.getOptionalString('backend.baseUrl');\n\n let configs = inputConfigs;\n\n let newBackendBaseUrl: string | undefined = undefined;\n let newAppBaseUrl: string | undefined = undefined;\n\n if (appBaseUrl && backendBaseUrl) {\n const appOrigin = new URL(appBaseUrl).origin;\n const backendOrigin = new URL(backendBaseUrl).origin;\n\n if (appOrigin === backendOrigin) {\n const maybeNewBackendBaseUrl = createLocalBaseUrl(backendBaseUrl);\n if (backendBaseUrl !== maybeNewBackendBaseUrl) {\n newBackendBaseUrl = maybeNewBackendBaseUrl;\n }\n }\n }\n\n if (appBaseUrl) {\n const maybeNewAppBaseUrl = createLocalBaseUrl(appBaseUrl);\n if (appBaseUrl !== maybeNewAppBaseUrl) {\n newAppBaseUrl = maybeNewAppBaseUrl;\n }\n }\n\n // Only add the relative config if there is actually data to add.\n if (newAppBaseUrl || newBackendBaseUrl) {\n configs = configs.concat({\n data: {\n app: newAppBaseUrl && {\n baseUrl: newAppBaseUrl,\n },\n backend: newBackendBaseUrl && {\n baseUrl: newBackendBaseUrl,\n },\n },\n context: 'relative-resolver',\n });\n }\n\n return configs;\n}\n"],"names":[],"mappings":";;AAqBA,SAAS,mBAAmB,OAAyB,EAAA;AACnD,EAAM,MAAA,GAAA,GAAM,IAAI,GAAA,CAAI,OAAO,CAAA,CAAA;AAC3B,EAAI,GAAA,CAAA,QAAA,GAAW,SAAS,QAAS,CAAA,QAAA,CAAA;AACjC,EAAI,GAAA,CAAA,QAAA,GAAW,SAAS,QAAS,CAAA,QAAA,CAAA;AACjC,EAAI,GAAA,CAAA,IAAA,GAAO,SAAS,QAAS,CAAA,IAAA,CAAA;AAC7B,EAAA,OAAO,GAAI,CAAA,QAAA,EAAW,CAAA,OAAA,CAAQ,OAAO,EAAE,CAAA,CAAA;AACzC,CAAA;AASO,SAAS,uBAAuB,YAAwC,EAAA;AAC7E,EAAM,MAAA,eAAA,GAAkB,YAAa,CAAA,WAAA,CAAY,YAAY,CAAA,CAAA;AAG7D,EAAM,MAAA,UAAA,GAAa,eAAgB,CAAA,iBAAA,CAAkB,aAAa,CAAA,CAAA;AAClE,EAAM,MAAA,cAAA,GAAiB,eAAgB,CAAA,iBAAA,CAAkB,iBAAiB,CAAA,CAAA;AAE1E,EAAA,IAAI,OAAU,GAAA,YAAA,CAAA;AAEd,EAAA,IAAI,iBAAwC,GAAA,KAAA,CAAA,CAAA;AAC5C,EAAA,IAAI,aAAoC,GAAA,KAAA,CAAA,CAAA;AAExC,EAAA,IAAI,cAAc,cAAgB,EAAA;AAChC,IAAA,MAAM,SAAY,GAAA,IAAI,GAAI,CAAA,UAAU,CAAE,CAAA,MAAA,CAAA;AACtC,IAAA,MAAM,aAAgB,GAAA,IAAI,GAAI,CAAA,cAAc,CAAE,CAAA,MAAA,CAAA;AAE9C,IAAA,IAAI,cAAc,aAAe,EAAA;AAC/B,MAAM,MAAA,sBAAA,GAAyB,mBAAmB,cAAc,CAAA,CAAA;AAChE,MAAA,IAAI,mBAAmB,sBAAwB,EAAA;AAC7C,QAAoB,iBAAA,GAAA,sBAAA,CAAA;AAAA,OACtB;AAAA,KACF;AAAA,GACF;AAEA,EAAA,IAAI,UAAY,EAAA;AACd,IAAM,MAAA,kBAAA,GAAqB,mBAAmB,UAAU,CAAA,CAAA;AACxD,IAAA,IAAI,eAAe,kBAAoB,EAAA;AACrC,MAAgB,aAAA,GAAA,kBAAA,CAAA;AAAA,KAClB;AAAA,GACF;AAGA,EAAA,IAAI,iBAAiB,iBAAmB,EAAA;AACtC,IAAA,OAAA,GAAU,QAAQ,MAAO,CAAA;AAAA,MACvB,IAAM,EAAA;AAAA,QACJ,KAAK,aAAiB,IAAA;AAAA,UACpB,OAAS,EAAA,aAAA;AAAA,SACX;AAAA,QACA,SAAS,iBAAqB,IAAA;AAAA,UAC5B,OAAS,EAAA,iBAAA;AAAA,SACX;AAAA,OACF;AAAA,MACA,OAAS,EAAA,mBAAA;AAAA,KACV,CAAA,CAAA;AAAA,GACH;AAEA,EAAO,OAAA,OAAA,CAAA;AACT;;;;"}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import ObservableImpl from 'zen-observable';
|
|
2
|
-
|
|
3
|
-
class BehaviorSubject {
|
|
4
|
-
isClosed;
|
|
5
|
-
currentValue;
|
|
6
|
-
terminatingError;
|
|
7
|
-
observable;
|
|
8
|
-
constructor(value) {
|
|
9
|
-
this.isClosed = false;
|
|
10
|
-
this.currentValue = value;
|
|
11
|
-
this.terminatingError = void 0;
|
|
12
|
-
this.observable = new ObservableImpl((subscriber) => {
|
|
13
|
-
if (this.isClosed) {
|
|
14
|
-
if (this.terminatingError) {
|
|
15
|
-
subscriber.error(this.terminatingError);
|
|
16
|
-
} else {
|
|
17
|
-
subscriber.complete();
|
|
18
|
-
}
|
|
19
|
-
return () => {
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
subscriber.next(this.currentValue);
|
|
23
|
-
this.subscribers.add(subscriber);
|
|
24
|
-
return () => {
|
|
25
|
-
this.subscribers.delete(subscriber);
|
|
26
|
-
};
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
subscribers = /* @__PURE__ */ new Set();
|
|
30
|
-
[Symbol.observable]() {
|
|
31
|
-
return this;
|
|
32
|
-
}
|
|
33
|
-
get closed() {
|
|
34
|
-
return this.isClosed;
|
|
35
|
-
}
|
|
36
|
-
next(value) {
|
|
37
|
-
if (this.isClosed) {
|
|
38
|
-
throw new Error("BehaviorSubject is closed");
|
|
39
|
-
}
|
|
40
|
-
this.currentValue = value;
|
|
41
|
-
this.subscribers.forEach((subscriber) => subscriber.next(value));
|
|
42
|
-
}
|
|
43
|
-
error(error) {
|
|
44
|
-
if (this.isClosed) {
|
|
45
|
-
throw new Error("BehaviorSubject is closed");
|
|
46
|
-
}
|
|
47
|
-
this.isClosed = true;
|
|
48
|
-
this.terminatingError = error;
|
|
49
|
-
this.subscribers.forEach((subscriber) => subscriber.error(error));
|
|
50
|
-
}
|
|
51
|
-
complete() {
|
|
52
|
-
if (this.isClosed) {
|
|
53
|
-
throw new Error("BehaviorSubject is closed");
|
|
54
|
-
}
|
|
55
|
-
this.isClosed = true;
|
|
56
|
-
this.subscribers.forEach((subscriber) => subscriber.complete());
|
|
57
|
-
}
|
|
58
|
-
subscribe(onNext, onError, onComplete) {
|
|
59
|
-
const observer = typeof onNext === "function" ? {
|
|
60
|
-
next: onNext,
|
|
61
|
-
error: onError,
|
|
62
|
-
complete: onComplete
|
|
63
|
-
} : onNext;
|
|
64
|
-
return this.observable.subscribe(observer);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export { BehaviorSubject };
|
|
69
|
-
//# sourceMappingURL=subjects.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"subjects.esm.js","sources":["../../../../../core-app-api/src/lib/subjects.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Observable } from '@backstage/types';\nimport ObservableImpl from 'zen-observable';\n\n// TODO(Rugvip): These are stopgap and probably incomplete implementations of subjects.\n// If we add a more complete Observables library they should be replaced.\n\n/**\n * A basic implementation of ReactiveX publish subjects.\n *\n * A subject is a convenient way to create an observable when you want\n * to fan out a single value to all subscribers.\n *\n * See http://reactivex.io/documentation/subject.html\n */\nexport class PublishSubject<T>\n implements Observable<T>, ZenObservable.SubscriptionObserver<T>\n{\n private isClosed = false;\n private terminatingError?: Error;\n\n private readonly observable = new ObservableImpl<T>(subscriber => {\n if (this.isClosed) {\n if (this.terminatingError) {\n subscriber.error(this.terminatingError);\n } else {\n subscriber.complete();\n }\n return () => {};\n }\n\n this.subscribers.add(subscriber);\n return () => {\n this.subscribers.delete(subscriber);\n };\n });\n\n private readonly subscribers = new Set<\n ZenObservable.SubscriptionObserver<T>\n >();\n\n [Symbol.observable]() {\n return this;\n }\n\n get closed() {\n return this.isClosed;\n }\n\n next(value: T) {\n if (this.isClosed) {\n throw new Error('PublishSubject is closed');\n }\n this.subscribers.forEach(subscriber => subscriber.next(value));\n }\n\n error(error: Error) {\n if (this.isClosed) {\n throw new Error('PublishSubject is closed');\n }\n this.isClosed = true;\n this.terminatingError = error;\n this.subscribers.forEach(subscriber => subscriber.error(error));\n }\n\n complete() {\n if (this.isClosed) {\n throw new Error('PublishSubject is closed');\n }\n this.isClosed = true;\n this.subscribers.forEach(subscriber => subscriber.complete());\n }\n\n subscribe(observer: ZenObservable.Observer<T>): ZenObservable.Subscription;\n subscribe(\n onNext: (value: T) => void,\n onError?: (error: any) => void,\n onComplete?: () => void,\n ): ZenObservable.Subscription;\n subscribe(\n onNext: ZenObservable.Observer<T> | ((value: T) => void),\n onError?: (error: any) => void,\n onComplete?: () => void,\n ): ZenObservable.Subscription {\n const observer =\n typeof onNext === 'function'\n ? {\n next: onNext,\n error: onError,\n complete: onComplete,\n }\n : onNext;\n\n return this.observable.subscribe(observer);\n }\n}\n\n/**\n * A basic implementation of ReactiveX behavior subjects.\n *\n * A subject is a convenient way to create an observable when you want\n * to fan out a single value to all subscribers.\n *\n * The BehaviorSubject will emit the most recently emitted value or error\n * whenever a new observer subscribes to the subject.\n *\n * See http://reactivex.io/documentation/subject.html\n */\n\nexport class BehaviorSubject<T>\n implements Observable<T>, ZenObservable.SubscriptionObserver<T>\n{\n private isClosed: boolean;\n private currentValue: T;\n private terminatingError: Error | undefined;\n private readonly observable: Observable<T>;\n\n constructor(value: T) {\n this.isClosed = false;\n this.currentValue = value;\n this.terminatingError = undefined;\n this.observable = new ObservableImpl<T>(subscriber => {\n if (this.isClosed) {\n if (this.terminatingError) {\n subscriber.error(this.terminatingError);\n } else {\n subscriber.complete();\n }\n return () => {};\n }\n\n subscriber.next(this.currentValue);\n\n this.subscribers.add(subscriber);\n return () => {\n this.subscribers.delete(subscriber);\n };\n });\n }\n\n private readonly subscribers = new Set<\n ZenObservable.SubscriptionObserver<T>\n >();\n\n [Symbol.observable]() {\n return this;\n }\n\n get closed() {\n return this.isClosed;\n }\n\n next(value: T) {\n if (this.isClosed) {\n throw new Error('BehaviorSubject is closed');\n }\n this.currentValue = value;\n this.subscribers.forEach(subscriber => subscriber.next(value));\n }\n\n error(error: Error) {\n if (this.isClosed) {\n throw new Error('BehaviorSubject is closed');\n }\n this.isClosed = true;\n this.terminatingError = error;\n this.subscribers.forEach(subscriber => subscriber.error(error));\n }\n\n complete() {\n if (this.isClosed) {\n throw new Error('BehaviorSubject is closed');\n }\n this.isClosed = true;\n this.subscribers.forEach(subscriber => subscriber.complete());\n }\n\n subscribe(observer: ZenObservable.Observer<T>): ZenObservable.Subscription;\n subscribe(\n onNext: (value: T) => void,\n onError?: (error: any) => void,\n onComplete?: () => void,\n ): ZenObservable.Subscription;\n subscribe(\n onNext: ZenObservable.Observer<T> | ((value: T) => void),\n onError?: (error: any) => void,\n onComplete?: () => void,\n ): ZenObservable.Subscription {\n const observer =\n typeof onNext === 'function'\n ? {\n next: onNext,\n error: onError,\n complete: onComplete,\n }\n : onNext;\n\n return this.observable.subscribe(observer);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
function toInternalTranslationRef(ref) {
|
|
2
|
-
const r = ref;
|
|
3
|
-
if (r.$$type !== "@backstage/TranslationRef") {
|
|
4
|
-
throw new Error(`Invalid translation ref, bad type '${r.$$type}'`);
|
|
5
|
-
}
|
|
6
|
-
if (r.version !== "v1") {
|
|
7
|
-
throw new Error(`Invalid translation ref, bad version '${r.version}'`);
|
|
8
|
-
}
|
|
9
|
-
return r;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export { toInternalTranslationRef };
|
|
13
|
-
//# sourceMappingURL=TranslationRef.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TranslationRef.esm.js","sources":["../../../../../core-plugin-api/src/translation/TranslationRef.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createTranslationResource,\n TranslationResource,\n} from './TranslationResource';\n\n/** @alpha */\nexport interface TranslationRef<\n TId extends string = string,\n TMessages extends { [key in string]: string } = { [key in string]: string },\n> {\n $$type: '@backstage/TranslationRef';\n\n id: TId;\n\n T: TMessages;\n}\n\n/** @internal */\ntype AnyMessages = { [key in string]: string };\n\n/** @ignore */\ntype AnyNestedMessages = { [key in string]: AnyNestedMessages | string };\n\n/**\n * Flattens a nested message declaration into a flat object with dot-separated keys.\n *\n * @ignore\n */\ntype FlattenedMessages<TMessages extends AnyNestedMessages> =\n // Flatten out object keys into a union structure of objects, e.g. { a: 'a', b: 'b' } -> { a: 'a' } | { b: 'b' }\n // Any nested object will be flattened into the individual unions, e.g. { a: 'a', b: { x: 'x', y: 'y' } } -> { a: 'a' } | { 'b.x': 'x', 'b.y': 'y' }\n // We create this structure by first nesting the desired union types into the original object, and\n // then extract them by indexing with `keyof TMessages` to form the union.\n // Throughout this the objects are wrapped up in a function parameter, which allows us to have the\n // final step of flipping this unions around to an intersection by inferring the function parameter.\n {\n [TKey in keyof TMessages]: (\n _: TMessages[TKey] extends infer TValue // \"local variable\" for the value\n ? TValue extends AnyNestedMessages\n ? FlattenedMessages<TValue> extends infer TNested // Recurse into nested messages, \"local variable\" for the result\n ? {\n [TNestedKey in keyof TNested as `${TKey & string}.${TNestedKey &\n string}`]: TNested[TNestedKey];\n }\n : never\n : { [_ in TKey]: TValue } // Primitive object values are passed through with the same key\n : never,\n ) => void;\n // The `[keyof TMessages]` extracts the object values union from our flattened structure, still wrapped up in function parameters.\n // The `extends (_: infer TIntersection) => void` flips the union to an intersection, at which point we have the correct type.\n }[keyof TMessages] extends (_: infer TIntersection) => void\n ? // This object mapping just expands similar to the Expand<> utility type, providing nicer type hints\n {\n readonly [TExpandKey in keyof TIntersection]: TIntersection[TExpandKey];\n }\n : never;\n\n/** @internal */\nexport interface InternalTranslationRef<\n TId extends string = string,\n TMessages extends { [key in string]: string } = { [key in string]: string },\n> extends TranslationRef<TId, TMessages> {\n version: 'v1';\n\n getDefaultMessages(): AnyMessages;\n\n getDefaultResource(): TranslationResource | undefined;\n}\n\n/** @alpha */\nexport interface TranslationRefOptions<\n TId extends string,\n TNestedMessages extends AnyNestedMessages,\n TTranslations extends {\n [language in string]: () => Promise<{\n default: {\n [key in keyof FlattenedMessages<TNestedMessages>]: string | null;\n };\n }>;\n },\n> {\n id: TId;\n messages: TNestedMessages;\n translations?: TTranslations;\n}\n\nfunction flattenMessages(nested: AnyNestedMessages): AnyMessages {\n const entries = new Array<[string, string]>();\n\n function visit(obj: AnyNestedMessages, prefix: string): void {\n for (const [key, value] of Object.entries(obj)) {\n if (typeof value === 'string') {\n entries.push([prefix + key, value]);\n } else {\n visit(value, `${prefix}${key}.`);\n }\n }\n }\n\n visit(nested, '');\n\n return Object.fromEntries(entries);\n}\n\n/** @internal */\nclass TranslationRefImpl<\n TId extends string,\n TNestedMessages extends AnyNestedMessages,\n> implements InternalTranslationRef<TId, FlattenedMessages<TNestedMessages>>\n{\n #id: TId;\n #messages: FlattenedMessages<TNestedMessages>;\n #resources: TranslationResource | undefined;\n\n constructor(options: TranslationRefOptions<TId, TNestedMessages, any>) {\n this.#id = options.id;\n this.#messages = flattenMessages(\n options.messages,\n ) as FlattenedMessages<TNestedMessages>;\n }\n\n $$type = '@backstage/TranslationRef' as const;\n\n version = 'v1' as const;\n\n get id(): TId {\n return this.#id;\n }\n\n get T(): never {\n throw new Error('Not implemented');\n }\n\n getDefaultMessages(): AnyMessages {\n return this.#messages;\n }\n\n setDefaultResource(resources: TranslationResource): void {\n this.#resources = resources;\n }\n\n getDefaultResource(): TranslationResource | undefined {\n return this.#resources;\n }\n\n toString() {\n return `TranslationRef{id=${this.id}}`;\n }\n}\n\n/** @alpha */\nexport function createTranslationRef<\n TId extends string,\n const TNestedMessages extends AnyNestedMessages,\n TTranslations extends {\n [language in string]: () => Promise<{\n default: {\n [key in keyof FlattenedMessages<TNestedMessages>]: string | null;\n };\n }>;\n },\n>(\n config: TranslationRefOptions<TId, TNestedMessages, TTranslations>,\n): TranslationRef<TId, FlattenedMessages<TNestedMessages>> {\n const ref = new TranslationRefImpl(config);\n if (config.translations) {\n ref.setDefaultResource(\n createTranslationResource({\n ref,\n translations: config.translations as any,\n }),\n );\n }\n return ref;\n}\n\n/** @internal */\nexport function toInternalTranslationRef<\n TId extends string,\n TMessages extends AnyMessages,\n>(ref: TranslationRef<TId, TMessages>): InternalTranslationRef<TId, TMessages> {\n const r = ref as InternalTranslationRef<TId, TMessages>;\n if (r.$$type !== '@backstage/TranslationRef') {\n throw new Error(`Invalid translation ref, bad type '${r.$$type}'`);\n }\n if (r.version !== 'v1') {\n throw new Error(`Invalid translation ref, bad version '${r.version}'`);\n }\n return r;\n}\n"],"names":[],"mappings":"AAiMO,SAAS,yBAGd,GAA6E,EAAA;AAC7E,EAAA,MAAM,CAAI,GAAA,GAAA,CAAA;AACV,EAAI,IAAA,CAAA,CAAE,WAAW,2BAA6B,EAAA;AAC5C,IAAA,MAAM,IAAI,KAAA,CAAM,CAAsC,mCAAA,EAAA,CAAA,CAAE,MAAM,CAAG,CAAA,CAAA,CAAA,CAAA;AAAA,GACnE;AACA,EAAI,IAAA,CAAA,CAAE,YAAY,IAAM,EAAA;AACtB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAyC,sCAAA,EAAA,CAAA,CAAE,OAAO,CAAG,CAAA,CAAA,CAAA,CAAA;AAAA,GACvE;AACA,EAAO,OAAA,CAAA,CAAA;AACT;;;;"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
function toInternalTranslationResource(resource) {
|
|
2
|
-
const r = resource;
|
|
3
|
-
if (r.$$type !== "@backstage/TranslationResource") {
|
|
4
|
-
throw new Error(`Invalid translation resource, bad type '${r.$$type}'`);
|
|
5
|
-
}
|
|
6
|
-
if (r.version !== "v1") {
|
|
7
|
-
throw new Error(`Invalid translation resource, bad version '${r.version}'`);
|
|
8
|
-
}
|
|
9
|
-
return r;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export { toInternalTranslationResource };
|
|
13
|
-
//# sourceMappingURL=TranslationResource.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TranslationResource.esm.js","sources":["../../../../../core-plugin-api/src/translation/TranslationResource.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n 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"],"names":[],"mappings":"AA2CO,SAAS,8BACd,QACkC,EAAA;AAClC,EAAA,MAAM,CAAI,GAAA,QAAA,CAAA;AACV,EAAI,IAAA,CAAA,CAAE,WAAW,gCAAkC,EAAA;AACjD,IAAA,MAAM,IAAI,KAAA,CAAM,CAA2C,wCAAA,EAAA,CAAA,CAAE,MAAM,CAAG,CAAA,CAAA,CAAA,CAAA;AAAA,GACxE;AACA,EAAI,IAAA,CAAA,CAAE,YAAY,IAAM,EAAA;AACtB,IAAA,MAAM,IAAI,KAAA,CAAM,CAA8C,2CAAA,EAAA,CAAA,CAAE,OAAO,CAAG,CAAA,CAAA,CAAA,CAAA;AAAA,GAC5E;AAEA,EAAO,OAAA,CAAA,CAAA;AACT;;;;"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { createExtension, createExtensionInput, ApiBlueprint, ThemeBlueprint, createComponentExtension, TranslationBlueprint, IconBundleBlueprint, coreExtensionData, ExtensionBoundary } from '@backstage/frontend-plugin-api';
|
|
3
|
-
|
|
4
|
-
const App = createExtension({
|
|
5
|
-
namespace: "app",
|
|
6
|
-
attachTo: { id: "root", input: "default" },
|
|
7
|
-
// ignored
|
|
8
|
-
inputs: {
|
|
9
|
-
apis: createExtensionInput([ApiBlueprint.dataRefs.factory]),
|
|
10
|
-
themes: createExtensionInput([ThemeBlueprint.dataRefs.theme]),
|
|
11
|
-
components: createExtensionInput([
|
|
12
|
-
createComponentExtension.componentDataRef
|
|
13
|
-
]),
|
|
14
|
-
translations: createExtensionInput([
|
|
15
|
-
TranslationBlueprint.dataRefs.translation
|
|
16
|
-
]),
|
|
17
|
-
icons: createExtensionInput([IconBundleBlueprint.dataRefs.icons]),
|
|
18
|
-
root: createExtensionInput([coreExtensionData.reactElement], {
|
|
19
|
-
singleton: true
|
|
20
|
-
})
|
|
21
|
-
},
|
|
22
|
-
output: [coreExtensionData.reactElement],
|
|
23
|
-
factory: ({ node, inputs }) => [
|
|
24
|
-
coreExtensionData.reactElement(
|
|
25
|
-
/* @__PURE__ */ React.createElement(ExtensionBoundary, { node }, inputs.root.get(coreExtensionData.reactElement))
|
|
26
|
-
)
|
|
27
|
-
]
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
export { App };
|
|
31
|
-
//# sourceMappingURL=App.esm.js.map
|