ngx-atomic-i18n 0.1.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.
@@ -0,0 +1,312 @@
1
+ import { computed, inject, Injectable, signal } from '@angular/core';
2
+ import { deepMerge, detectPreferredLang, filterNewKeysDeep, getNested, normalizeLangCode, parseICU, toObservable } from './translate.util';
3
+ import { FIFOCache } from './FIFO.model';
4
+ import { ICU_FORMATTER_TOKEN, TRANSLATION_CONFIG, TRANSLATION_LOADER } from './translate.token';
5
+ import * as i0 from "@angular/core";
6
+ /** Maximum compiled formatter entries retained before evicting older ones. */
7
+ const MAX_CACHE_SIZE = 30;
8
+ /**
9
+ * Central cache and orchestration layer for loading translation namespaces,
10
+ * compiling ICU messages, and serving formatted strings to the higher-level API.
11
+ */
12
+ export class TranslationCoreService {
13
+ /** Immutable runtime configuration injected from the library bootstrap. */
14
+ _config = inject(TRANSLATION_CONFIG);
15
+ /** Active loader used to fetch namespace JSON payloads. */
16
+ _loader = inject(TRANSLATION_LOADER);
17
+ /** Optional custom ICU formatter constructor supplied by the host application. */
18
+ _ICU = inject(ICU_FORMATTER_TOKEN, { optional: true });
19
+ debugEnabled = !!this._config.debug;
20
+ /** Reactive language state tracking the current locale. */
21
+ _lang = signal(detectPreferredLang(this._config));
22
+ lang = this._lang.asReadonly();
23
+ /** Translation documents keyed by language then namespace. */
24
+ _jsonCache = signal(new Map()); // lang => namespace => key
25
+ /** Version fingerprints captured alongside each namespace entry. */
26
+ _versionMap = signal(new Map()); // lang => namespace => version
27
+ /** Least-recently-used cache of compiled ICU formatters. */
28
+ _formatterCache = new FIFOCache(MAX_CACHE_SIZE);
29
+ _missingKeyCache = new Set();
30
+ _inflight = new Map();
31
+ /** Caches compiled ICU expressions (with or without custom formatters). */
32
+ _icuCompiledCache = new Map();
33
+ onLangChange = toObservable(this._lang);
34
+ fallbackLang = this._config.fallbackLang ?? 'en';
35
+ get currentLang() {
36
+ return this._lang.asReadonly()();
37
+ }
38
+ readySignal(namespace, version) {
39
+ return computed(() => this.hasJsonCacheValue(this.lang(), namespace, version));
40
+ }
41
+ setLang(lang) {
42
+ const attempted = lang ?? detectPreferredLang(this._config);
43
+ const currentLang = normalizeLangCode(attempted, this._config.supportedLangs);
44
+ if (!currentLang) {
45
+ this.warn(`Unsupported language requested: ${attempted}`);
46
+ return;
47
+ }
48
+ if (this._lang() !== currentLang) {
49
+ this._lang.set(currentLang);
50
+ this.log(`Switched active language to "${currentLang}".`);
51
+ this._icuCompiledCache.clear();
52
+ const isBroswer = typeof window !== 'undefined';
53
+ if (isBroswer) {
54
+ try {
55
+ localStorage.setItem('lang', this._lang());
56
+ }
57
+ catch (err) {
58
+ this.warn('Failed to persist language to localStorage.', err);
59
+ }
60
+ }
61
+ }
62
+ }
63
+ async load(nsKey, fetchFn) {
64
+ const parts = nsKey.split(':');
65
+ const lang = parts[0];
66
+ const namespace = parts[1];
67
+ const version = parts[2];
68
+ if (this.hasJsonCacheValue(lang, namespace, version)) {
69
+ this.log(`Namespace "${namespace}" for "${lang}" is already cached. Skip loader.`);
70
+ return;
71
+ }
72
+ // coalesce concurrent loads for the same nsKey
73
+ if (this._inflight.has(nsKey)) {
74
+ this.log(`Namespace "${namespace}" for "${lang}" is already loading. Reusing in-flight request.`);
75
+ await this._inflight.get(nsKey);
76
+ return;
77
+ }
78
+ this.log(`Loading namespace "${namespace}" for "${lang}"${version ? ` (version ${version})` : ''}.`);
79
+ const p = (async () => {
80
+ try {
81
+ const json = await fetchFn();
82
+ this.handleNewTranslations(json, lang, namespace, version);
83
+ this.log(`Namespace "${namespace}" for "${lang}" loaded successfully.`);
84
+ }
85
+ catch (error) {
86
+ this.error(`Failed to load namespace "${namespace}" for "${lang}".`, error);
87
+ throw error;
88
+ }
89
+ finally {
90
+ this._inflight.delete(nsKey);
91
+ }
92
+ })();
93
+ this._inflight.set(nsKey, p);
94
+ await p;
95
+ }
96
+ getAndCreateFormatter(nsKey, key) {
97
+ const cacheKey = `${nsKey}:${key}`;
98
+ if (this._formatterCache.has(cacheKey))
99
+ return this._formatterCache.get(cacheKey);
100
+ const [lang, namespace] = nsKey.split(':');
101
+ const raw = getNested(this._jsonCache().get(lang)?.get(namespace), key);
102
+ if (raw === undefined)
103
+ return;
104
+ let result;
105
+ if (this._ICU) {
106
+ const k = `${raw}|${this.lang()}`;
107
+ const exist = this._icuCompiledCache.get(k);
108
+ if (exist) {
109
+ result = exist;
110
+ }
111
+ else {
112
+ result = new this._ICU(raw, this.lang());
113
+ this._icuCompiledCache.set(k, result);
114
+ }
115
+ }
116
+ else {
117
+ const k = raw;
118
+ const exist = this._icuCompiledCache.get(k);
119
+ if (exist) {
120
+ result = exist;
121
+ }
122
+ else {
123
+ result = { format: (p) => parseICU(raw, p) };
124
+ this._icuCompiledCache.set(k, result);
125
+ }
126
+ }
127
+ this._formatterCache.set(cacheKey, result);
128
+ return result;
129
+ }
130
+ findFallbackFormatter(key, exclude, version) {
131
+ const namespaces = Array.isArray(this._config.fallbackNamespace)
132
+ ? this._config.fallbackNamespace
133
+ : [this._config.fallbackNamespace ?? ''];
134
+ for (const namespace of namespaces) {
135
+ const nsKey = version ? `${this.currentLang}:${namespace}:${version}` : `${this.currentLang}:${namespace}`;
136
+ if (exclude.includes(nsKey))
137
+ continue;
138
+ const missKey = version
139
+ ? `${this.currentLang}:${namespace}:${version}:${key}`
140
+ : `${this.currentLang}:${namespace}:${key}`;
141
+ if (this._missingKeyCache.has(missKey))
142
+ continue;
143
+ const result = this.getAndCreateFormatter(nsKey, key);
144
+ if (result)
145
+ return result;
146
+ this._missingKeyCache.add(missKey);
147
+ }
148
+ return undefined;
149
+ }
150
+ async preloadNamespaces(namespaces, lang) {
151
+ const roots = Array.isArray(this._config.i18nRoots) ? this._config.i18nRoots : [this._config.i18nRoots];
152
+ const loadList = namespaces.filter(namespace => !this.hasJsonCacheValue(lang, namespace));
153
+ const jsonArray = await Promise.all(loadList.map(namespace => this._loader.load(roots, namespace, lang)));
154
+ jsonArray.forEach((json, index) => this.handleNewTranslations(json, lang, loadList[index], undefined));
155
+ }
156
+ handleNewTranslations(json, lang, namespace, version) {
157
+ const map = new Map(this._jsonCache());
158
+ const langMap = new Map(this._jsonCache().get(lang));
159
+ langMap.set(namespace, json);
160
+ map.set(lang, langMap);
161
+ this._jsonCache.set(map);
162
+ const vMap = new Map(this._versionMap());
163
+ const vLangMap = new Map(this._versionMap().get(lang));
164
+ vLangMap.set(namespace, version);
165
+ vMap.set(lang, vLangMap);
166
+ this._versionMap.set(vMap);
167
+ // Invalidate formatter cache for this namespace (covers with/without version)
168
+ const nsKey = `${lang}:${namespace}:`;
169
+ this._formatterCache.deleteWhere((k) => k.startsWith(nsKey));
170
+ this._missingKeyCache.clear();
171
+ if (this.debugEnabled) {
172
+ const keyCount = json && typeof json === 'object' ? Object.keys(json).length : 0;
173
+ this.log(`Cached namespace "${namespace}" for "${lang}" (${keyCount} top-level keys).`);
174
+ }
175
+ }
176
+ hasJsonCacheValue(lang, namespace, version) {
177
+ const exists = this._jsonCache().get(lang)?.get(namespace) !== undefined;
178
+ if (!exists)
179
+ return false;
180
+ if (version !== undefined) {
181
+ const stored = this._versionMap().get(lang)?.get(namespace);
182
+ return stored === version;
183
+ }
184
+ return true;
185
+ }
186
+ addResourceBundle(lang, namespace, bundle, deep = true, overwrite = true) {
187
+ const map = new Map(this._jsonCache());
188
+ const oldLangMap = map.get(lang);
189
+ const langMap = oldLangMap ? new Map(map.get(lang)) : new Map();
190
+ const existTranslations = langMap.get(namespace) ?? {};
191
+ let merged;
192
+ if (deep) {
193
+ merged = overwrite
194
+ ? deepMerge(existTranslations, bundle)
195
+ : deepMerge(existTranslations, filterNewKeysDeep(bundle, existTranslations));
196
+ }
197
+ else {
198
+ merged = overwrite
199
+ ? { ...existTranslations, ...bundle }
200
+ : { ...bundle };
201
+ if (!overwrite) {
202
+ for (const key in existTranslations) {
203
+ if (!(key in merged)) {
204
+ merged[key] = existTranslations[key];
205
+ }
206
+ }
207
+ }
208
+ }
209
+ langMap.set(namespace, merged);
210
+ map.set(lang, langMap);
211
+ this._jsonCache.set(map);
212
+ }
213
+ addResources(lang, namespace, obj, overwrite = true) {
214
+ this.addResourceBundle(lang, namespace, obj, false, overwrite);
215
+ }
216
+ addResource(lang, namespace, key, val, overwrite = true) {
217
+ this.addResources(lang, namespace, { [key]: val }, overwrite);
218
+ }
219
+ getAllBundle() {
220
+ return this._jsonCache();
221
+ }
222
+ hasResourceBundle(lang, namespace) {
223
+ return !!this._jsonCache().get(lang)?.has(namespace);
224
+ }
225
+ getResourceBundle(lang, namespace) {
226
+ return this._jsonCache().get(lang)?.get(namespace);
227
+ }
228
+ removeResourceBundle(lang, namespace) {
229
+ const map = new Map(this._jsonCache());
230
+ const langMap = new Map(map.get(lang));
231
+ langMap.delete(namespace);
232
+ map.set(lang, langMap);
233
+ this._jsonCache.set(map);
234
+ // Evict all formatter cache entries that belong to this lang:namespace (with or without version)
235
+ // Keys are in form `${nsKey}:${key}` where nsKey may include version
236
+ const prefix = `${lang}:${namespace}:`;
237
+ this._formatterCache.deleteWhere((k) => k.startsWith(prefix));
238
+ // also clear missing-key entries for this namespace
239
+ for (const k of Array.from(this._missingKeyCache)) {
240
+ if (k.startsWith(prefix))
241
+ this._missingKeyCache.delete(k);
242
+ }
243
+ }
244
+ /** Clear everything: data, versions, formatters, missing keys, inflight */
245
+ clearAll() {
246
+ this._jsonCache.set(new Map());
247
+ this._versionMap.set(new Map());
248
+ this._formatterCache.clear();
249
+ this._missingKeyCache.clear();
250
+ this._inflight.clear();
251
+ this._icuCompiledCache.clear();
252
+ }
253
+ /** Clear all resources for a language */
254
+ clearLang(lang) {
255
+ const map = new Map(this._jsonCache());
256
+ map.delete(lang);
257
+ this._jsonCache.set(map);
258
+ const vmap = new Map(this._versionMap());
259
+ vmap.delete(lang);
260
+ this._versionMap.set(vmap);
261
+ this._formatterCache.deleteWhere((k) => k.startsWith(`${lang}:`));
262
+ for (const k of Array.from(this._missingKeyCache)) {
263
+ if (k.startsWith(`${lang}:`))
264
+ this._missingKeyCache.delete(k);
265
+ }
266
+ for (const k of Array.from(this._icuCompiledCache.keys())) {
267
+ if (k.endsWith(`|${lang}`))
268
+ this._icuCompiledCache.delete(k);
269
+ }
270
+ }
271
+ /** Clear a specific namespace for a language */
272
+ clearNamespace(lang, namespace) {
273
+ this.removeResourceBundle(lang, namespace);
274
+ }
275
+ getResource(lang, namespace, key) {
276
+ return getNested(this._jsonCache().get(lang)?.get(namespace), key);
277
+ }
278
+ log(message, ...details) {
279
+ if (!this.debugEnabled)
280
+ return;
281
+ if (details.length) {
282
+ console.info(`[ngx-atomic-i18n] ${message}`, ...details);
283
+ }
284
+ else {
285
+ console.info(`[ngx-atomic-i18n] ${message}`);
286
+ }
287
+ }
288
+ error(message, error) {
289
+ if (!this.debugEnabled)
290
+ return;
291
+ console.error(`[ngx-atomic-i18n] ${message}`, error);
292
+ }
293
+ warn(message, ...details) {
294
+ if (!this.debugEnabled)
295
+ return;
296
+ if (details.length) {
297
+ console.warn(`[ngx-atomic-i18n] ${message}`, ...details);
298
+ }
299
+ else {
300
+ console.warn(`[ngx-atomic-i18n] ${message}`);
301
+ }
302
+ }
303
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationCoreService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
304
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationCoreService, providedIn: 'root' });
305
+ }
306
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationCoreService, decorators: [{
307
+ type: Injectable,
308
+ args: [{
309
+ providedIn: 'root'
310
+ }]
311
+ }] });
312
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNsYXRpb24tY29yZS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWF0b21pYy1pMThuL3NyYy9saWIvdHJhbnNsYXRpb24tY29yZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBVSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDN0UsT0FBTyxFQUFFLFNBQVMsRUFBRSxtQkFBbUIsRUFBRSxpQkFBaUIsRUFBRSxTQUFTLEVBQUUsaUJBQWlCLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRTNJLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDekMsT0FBTyxFQUFFLG1CQUFtQixFQUFFLGtCQUFrQixFQUFFLGtCQUFrQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7O0FBR2hHLDhFQUE4RTtBQUM5RSxNQUFNLGNBQWMsR0FBRyxFQUFFLENBQUM7QUFJMUI7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLHNCQUFzQjtJQUNqQywyRUFBMkU7SUFDMUQsT0FBTyxHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ3RELDJEQUEyRDtJQUMxQyxPQUFPLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixDQUFDLENBQUM7SUFDdEQsa0ZBQWtGO0lBQ2pFLElBQUksR0FBRyxNQUFNLENBQUMsbUJBQW1CLEVBQUUsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQXdFLENBQUE7SUFDN0gsWUFBWSxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztJQUVyRCwyREFBMkQ7SUFDMUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUMxRCxJQUFJLEdBQUcsSUFB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LENBQUMsQ0FBQztRQUMzRCxDQUFDO2FBQU0sQ0FBQztZQUNOLE9BQU8sQ0FBQyxJQUFJLENBQUMscUJBQXFCLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDL0MsQ0FBQztJQUNILENBQUM7d0dBN1NVLHNCQUFzQjs0R0FBdEIsc0JBQXNCLGNBTnJCLE1BQU07OzRGQU1QLHNCQUFzQjtrQkFQbEMsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjb21wdXRlZCwgaW5qZWN0LCBJbmplY3RhYmxlLCBTaWduYWwsIHNpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgZGVlcE1lcmdlLCBkZXRlY3RQcmVmZXJyZWRMYW5nLCBmaWx0ZXJOZXdLZXlzRGVlcCwgZ2V0TmVzdGVkLCBub3JtYWxpemVMYW5nQ29kZSwgcGFyc2VJQ1UsIHRvT2JzZXJ2YWJsZSB9IGZyb20gJy4vdHJhbnNsYXRlLnV0aWwnO1xuXG5pbXBvcnQgeyBGSUZPQ2FjaGUgfSBmcm9tICcuL0ZJRk8ubW9kZWwnO1xuaW1wb3J0IHsgSUNVX0ZPUk1BVFRFUl9UT0tFTiwgVFJBTlNMQVRJT05fQ09ORklHLCBUUkFOU0xBVElPTl9MT0FERVIgfSBmcm9tICcuL3RyYW5zbGF0ZS50b2tlbic7XG5pbXBvcnQgeyBGb3JtYXRSZXN1bHQsIG5zS2V5LCBUcmFuc2xhdGlvbnMgfSBmcm9tICcuL3RyYW5zbGF0ZS50eXBlJztcblxuLyoqIE1heGltdW0gY29tcGlsZWQgZm9ybWF0dGVyIGVudHJpZXMgcmV0YWluZWQgYmVmb3JlIGV2aWN0aW5nIG9sZGVyIG9uZXMuICovXG5jb25zdCBNQVhfQ0FDSEVfU0laRSA9IDMwO1xuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG4vKipcbiAqIENlbnRyYWwgY2FjaGUgYW5kIG9yY2hlc3RyYXRpb24gbGF5ZXIgZm9yIGxvYWRpbmcgdHJhbnNsYXRpb24gbmFtZXNwYWNlcyxcbiAqIGNvbXBpbGluZyBJQ1UgbWVzc2FnZXMsIGFuZCBzZXJ2aW5nIGZvcm1hdHRlZCBzdHJpbmdzIHRvIHRoZSBoaWdoZXItbGV2ZWwgQVBJLlxuICovXG5leHBvcnQgY2xhc3MgVHJhbnNsYXRpb25Db3JlU2VydmljZSB7XG4gIC8qKiBJbW11dGFibGUgcnVudGltZSBjb25maWd1cmF0aW9uIGluamVjdGVkIGZyb20gdGhlIGxpYnJhcnkgYm9vdHN0cmFwLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IF9jb25maWcgPSBpbmplY3QoVFJBTlNMQVRJT05fQ09ORklHKTtcbiAgLyoqIEFjdGl2ZSBsb2FkZXIgdXNlZCB0byBmZXRjaCBuYW1lc3BhY2UgSlNPTiBwYXlsb2Fkcy4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBfbG9hZGVyID0gaW5qZWN0KFRSQU5TTEFUSU9OX0xPQURFUik7XG4gIC8qKiBPcHRpb25hbCBjdXN0b20gSUNVIGZvcm1hdHRlciBjb25zdHJ1Y3RvciBzdXBwbGllZCBieSB0aGUgaG9zdCBhcHBsaWNhdGlvbi4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBfSUNVID0gaW5qZWN0KElDVV9GT1JNQVRURVJfVE9LRU4sIHsgb3B0aW9uYWw6IHRydWUgfSkgYXMgdW5rbm93biBhcyAobmV3IChyYXc6IHN0cmluZywgbGFuZzogc3RyaW5nKSA9PiBGb3JtYXRSZXN1bHQpIHwgbnVsbFxuICBwcml2YXRlIHJlYWRvbmx5IGRlYnVnRW5hYmxlZCA9ICEhdGhpcy5fY29uZmlnLmRlYnVnO1xuXG4gIC8qKiBSZWFjdGl2ZSBsYW5ndWFnZSBzdGF0ZSB0cmFja2luZyB0aGUgY3VycmVudCBsb2NhbGUuICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX2xhbmcgPSBzaWduYWwoZGV0ZWN0UHJlZmVycmVkTGFuZyh0aGlzLl9jb25maWcpKTtcbiAgcmVhZG9ubHkgbGFuZyA9IHRoaXMuX2xhbmcuYXNSZWFkb25seSgpO1xuXG4gIC8qKiBUcmFuc2xhdGlvbiBkb2N1bWVudHMga2V5ZWQgYnkgbGFuZ3VhZ2UgdGhlbiBuYW1lc3BhY2UuICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX2pzb25DYWNoZSA9IHNpZ25hbChuZXcgTWFwPHN0cmluZywgTWFwPHN0cmluZywgUmVjb3JkPHN0cmluZywgYW55Pj4+KCkpOyAvLyBsYW5nID0+IG5hbWVzcGFjZSA9PiBrZXlcbiAgLyoqIFZlcnNpb24gZmluZ2VycHJpbnRzIGNhcHR1cmVkIGFsb25nc2lkZSBlYWNoIG5hbWVzcGFjZSBlbnRyeS4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBfdmVyc2lvbk1hcCA9IHNpZ25hbChuZXcgTWFwPHN0cmluZywgTWFwPHN0cmluZywgc3RyaW5nIHwgdW5kZWZpbmVkPj4oKSk7IC8vIGxhbmcgPT4gbmFtZXNwYWNlID0+IHZlcnNpb25cbiAgLyoqIExlYXN0LXJlY2VudGx5LXVzZWQgY2FjaGUgb2YgY29tcGlsZWQgSUNVIGZvcm1hdHRlcnMuICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX2Zvcm1hdHRlckNhY2hlID0gbmV3IEZJRk9DYWNoZTxuc0tleSwgRm9ybWF0UmVzdWx0PihNQVhfQ0FDSEVfU0laRSk7XG4gIHByaXZhdGUgX21pc3NpbmdLZXlDYWNoZSA9IG5ldyBTZXQ8bnNLZXk+KCk7XG4gIHByaXZhdGUgX2luZmxpZ2h0ID0gbmV3IE1hcDxzdHJpbmcsIFByb21pc2U8dm9pZD4+KCk7XG4gIC8qKiBDYWNoZXMgY29tcGlsZWQgSUNVIGV4cHJlc3Npb25zICh3aXRoIG9yIHdpdGhvdXQgY3VzdG9tIGZvcm1hdHRlcnMpLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IF9pY3VDb21waWxlZENhY2hlID0gbmV3IE1hcDxzdHJpbmcsIEZvcm1hdFJlc3VsdD4oKTtcblxuICByZWFkb25seSBvbkxhbmdDaGFuZ2UgPSB0b09ic2VydmFibGUodGhpcy5fbGFuZyk7XG4gIHJlYWRvbmx5IGZhbGxiYWNrTGFuZyA9IHRoaXMuX2NvbmZpZy5mYWxsYmFja0xhbmcgPz8gJ2VuJztcblxuICBnZXQgY3VycmVudExhbmcoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fbGFuZy5hc1JlYWRvbmx5KCkoKTtcbiAgfVxuXG4gIHJlYWR5U2lnbmFsKG5hbWVzcGFjZTogc3RyaW5nLCB2ZXJzaW9uPzogc3RyaW5nKTogU2lnbmFsPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gY29tcHV0ZWQoKCkgPT4gdGhpcy5oYXNKc29uQ2FjaGVWYWx1ZSh0aGlzLmxhbmcoKSwgbmFtZXNwYWNlLCB2ZXJzaW9uKSk7XG4gIH1cblxuICBzZXRMYW5nKGxhbmc/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBhdHRlbXB0ZWQgPSBsYW5nID8/IGRldGVjdFByZWZlcnJlZExhbmcodGhpcy5fY29uZmlnKTtcbiAgICBjb25zdCBjdXJyZW50TGFuZyA9IG5vcm1hbGl6ZUxhbmdDb2RlKGF0dGVtcHRlZCwgdGhpcy5fY29uZmlnLnN1cHBvcnRlZExhbmdzKTtcblxuICAgIGlmICghY3VycmVudExhbmcpIHtcbiAgICAgIHRoaXMud2FybihgVW5zdXBwb3J0ZWQgbGFuZ3VhZ2UgcmVxdWVzdGVkOiAke2F0dGVtcHRlZH1gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHRoaXMuX2xhbmcoKSAhPT0gY3VycmVudExhbmcpIHtcbiAgICAgIHRoaXMuX2xhbmcuc2V0KGN1cnJlbnRMYW5nKTtcbiAgICAgIHRoaXMubG9nKGBTd2l0Y2hlZCBhY3RpdmUgbGFuZ3VhZ2UgdG8gXCIke2N1cnJlbnRMYW5nfVwiLmApO1xuICAgICAgdGhpcy5faWN1Q29tcGlsZWRDYWNoZS5jbGVhcigpO1xuICAgICAgY29uc3QgaXNCcm9zd2VyID0gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCc7XG4gICAgICBpZiAoaXNCcm9zd2VyKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ2xhbmcnLCB0aGlzLl9sYW5nKCkpO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICB0aGlzLndhcm4oJ0ZhaWxlZCB0byBwZXJzaXN0IGxhbmd1YWdlIHRvIGxvY2FsU3RvcmFnZS4nLCBlcnIpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgbG9hZChuc0tleTogc3RyaW5nLCBmZXRjaEZuOiAoKSA9PiBQcm9taXNlPFRyYW5zbGF0aW9ucz4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBwYXJ0cyA9IG5zS2V5LnNwbGl0KCc6Jyk7XG4gICAgY29uc3QgbGFuZyA9IHBhcnRzWzBdO1xuICAgIGNvbnN0IG5hbWVzcGFjZSA9IHBhcnRzWzFdO1xuICAgIGNvbnN0IHZlcnNpb24gPSBwYXJ0c1syXTtcbiAgICBpZiAodGhpcy5oYXNKc29uQ2FjaGVWYWx1ZShsYW5nLCBuYW1lc3BhY2UsIHZlcnNpb24pKSB7XG4gICAgICB0aGlzLmxvZyhgTmFtZXNwYWNlIFwiJHtuYW1lc3BhY2V9XCIgZm9yIFwiJHtsYW5nfVwiIGlzIGFscmVhZHkgY2FjaGVkLiBTa2lwIGxvYWRlci5gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBjb2FsZXNjZSBjb25jdXJyZW50IGxvYWRzIGZvciB0aGUgc2FtZSBuc0tleVxuICAgIGlmICh0aGlzLl9pbmZsaWdodC5oYXMobnNLZXkpKSB7XG4gICAgICB0aGlzLmxvZyhgTmFtZXNwYWNlIFwiJHtuYW1lc3BhY2V9XCIgZm9yIFwiJHtsYW5nfVwiIGlzIGFscmVhZHkgbG9hZGluZy4gUmV1c2luZyBpbi1mbGlnaHQgcmVxdWVzdC5gKTtcbiAgICAgIGF3YWl0IHRoaXMuX2luZmxpZ2h0LmdldChuc0tleSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5sb2coYExvYWRpbmcgbmFtZXNwYWNlIFwiJHtuYW1lc3BhY2V9XCIgZm9yIFwiJHtsYW5nfVwiJHt2ZXJzaW9uID8gYCAodmVyc2lvbiAke3ZlcnNpb259KWAgOiAnJ30uYCk7XG4gICAgY29uc3QgcCA9IChhc3luYyAoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBqc29uID0gYXdhaXQgZmV0Y2hGbigpO1xuICAgICAgICB0aGlzLmhhbmRsZU5ld1RyYW5zbGF0aW9ucyhqc29uLCBsYW5nLCBuYW1lc3BhY2UsIHZlcnNpb24pO1xuICAgICAgICB0aGlzLmxvZyhgTmFtZXNwYWNlIFwiJHtuYW1lc3BhY2V9XCIgZm9yIFwiJHtsYW5nfVwiIGxvYWRlZCBzdWNjZXNzZnVsbHkuYCk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICB0aGlzLmVycm9yKGBGYWlsZWQgdG8gbG9hZCBuYW1lc3BhY2UgXCIke25hbWVzcGFjZX1cIiBmb3IgXCIke2xhbmd9XCIuYCwgZXJyb3IpO1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIHRoaXMuX2luZmxpZ2h0LmRlbGV0ZShuc0tleSk7XG4gICAgICB9XG4gICAgfSkoKTtcbiAgICB0aGlzLl9pbmZsaWdodC5zZXQobnNLZXksIHApO1xuICAgIGF3YWl0IHA7XG4gIH1cblxuICBnZXRBbmRDcmVhdGVGb3JtYXR0ZXIobnNLZXk6IHN0cmluZywga2V5OiBzdHJpbmcpOiBGb3JtYXRSZXN1bHQgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGNhY2hlS2V5ID0gYCR7bnNLZXl9OiR7a2V5fWA7XG4gICAgaWYgKHRoaXMuX2Zvcm1hdHRlckNhY2hlLmhhcyhjYWNoZUtleSkpIHJldHVybiB0aGlzLl9mb3JtYXR0ZXJDYWNoZS5nZXQoY2FjaGVLZXkpO1xuICAgIGNvbnN0IFtsYW5nLCBuYW1lc3BhY2VdID0gbnNLZXkuc3BsaXQoJzonKTtcbiAgICBjb25zdCByYXcgPSBnZXROZXN0ZWQodGhpcy5fanNvbkNhY2hlKCkuZ2V0KGxhbmcpPy5nZXQobmFtZXNwYWNlKSwga2V5KTtcbiAgICBpZiAocmF3ID09PSB1bmRlZmluZWQpIHJldHVybjtcbiAgICBsZXQgcmVzdWx0OiBGb3JtYXRSZXN1bHQ7XG4gICAgaWYgKHRoaXMuX0lDVSkge1xuICAgICAgY29uc3QgayA9IGAke3Jhd318JHt0aGlzLmxhbmcoKX1gO1xuICAgICAgY29uc3QgZXhpc3QgPSB0aGlzLl9pY3VDb21waWxlZENhY2hlLmdldChrKTtcbiAgICAgIGlmIChleGlzdCkge1xuICAgICAgICByZXN1bHQgPSBleGlzdDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdCA9IG5ldyB0aGlzLl9JQ1UocmF3LCB0aGlzLmxhbmcoKSk7XG4gICAgICAgIHRoaXMuX2ljdUNvbXBpbGVkQ2FjaGUuc2V0KGssIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGsgPSByYXc7XG4gICAgICBjb25zdCBleGlzdCA9IHRoaXMuX2ljdUNvbXBpbGVkQ2FjaGUuZ2V0KGspO1xuICAgICAgaWYgKGV4aXN0KSB7XG4gICAgICAgIHJlc3VsdCA9IGV4aXN0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdWx0ID0geyBmb3JtYXQ6IChwKSA9PiBwYXJzZUlDVShyYXcsIHApIH07XG4gICAgICAgIHRoaXMuX2ljdUNvbXBpbGVkQ2FjaGUuc2V0KGssIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMuX2Zvcm1hdHRlckNhY2hlLnNldChjYWNoZUtleSwgcmVzdWx0KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgZmluZEZhbGxiYWNrRm9ybWF0dGVyKGtleTogc3RyaW5nLCBleGNsdWRlOiBzdHJpbmdbXSwgdmVyc2lvbj86IHN0cmluZyk6IEZvcm1hdFJlc3VsdCB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgbmFtZXNwYWNlcyA9IEFycmF5LmlzQXJyYXkodGhpcy5fY29uZmlnLmZhbGxiYWNrTmFtZXNwYWNlKVxuICAgICAgPyB0aGlzLl9jb25maWcuZmFsbGJhY2tOYW1lc3BhY2VcbiAgICAgIDogW3RoaXMuX2NvbmZpZy5mYWxsYmFja05hbWVzcGFjZSA/PyAnJ11cbiAgICBmb3IgKGNvbnN0IG5hbWVzcGFjZSBvZiBuYW1lc3BhY2VzKSB7XG4gICAgICBjb25zdCBuc0tleSA9IHZlcnNpb24gPyBgJHt0aGlzLmN1cnJlbnRMYW5nfToke25hbWVzcGFjZX06JHt2ZXJzaW9ufWAgOiBgJHt0aGlzLmN1cnJlbnRMYW5nfToke25hbWVzcGFjZX1gO1xuICAgICAgaWYgKGV4Y2x1ZGUuaW5jbHVkZXMobnNLZXkpKSBjb250aW51ZTtcbiAgICAgIGNvbnN0IG1pc3NLZXkgPSB2ZXJzaW9uXG4gICAgICAgID8gYCR7dGhpcy5jdXJyZW50TGFuZ306JHtuYW1lc3BhY2V9OiR7dmVyc2lvbn06JHtrZXl9YFxuICAgICAgICA6IGAke3RoaXMuY3VycmVudExhbmd9OiR7bmFtZXNwYWNlfToke2tleX1gO1xuICAgICAgaWYgKHRoaXMuX21pc3NpbmdLZXlDYWNoZS5oYXMobWlzc0tleSkpIGNvbnRpbnVlO1xuICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5nZXRBbmRDcmVhdGVGb3JtYXR0ZXIobnNLZXksIGtleSk7XG4gICAgICBpZiAocmVzdWx0KSByZXR1cm4gcmVzdWx0O1xuICAgICAgdGhpcy5fbWlzc2luZ0tleUNhY2hlLmFkZChtaXNzS2V5KTtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGFzeW5jIHByZWxvYWROYW1lc3BhY2VzKG5hbWVzcGFjZXM6IHN0cmluZ1tdLCBsYW5nOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCByb290cyA9IEFycmF5LmlzQXJyYXkodGhpcy5fY29uZmlnLmkxOG5Sb290cykgPyB0aGlzLl9jb25maWcuaTE4blJvb3RzIDogW3RoaXMuX2NvbmZpZy5pMThuUm9vdHNdO1xuICAgIGNvbnN0IGxvYWRMaXN0ID0gbmFtZXNwYWNlcy5maWx0ZXIobmFtZXNwYWNlID0+ICF0aGlzLmhhc0pzb25DYWNoZVZhbHVlKGxhbmcsIG5hbWVzcGFjZSkpO1xuICAgIGNvbnN0IGpzb25BcnJheSA9IGF3YWl0IFByb21pc2UuYWxsKGxvYWRMaXN0Lm1hcChuYW1lc3BhY2UgPT4gdGhpcy5fbG9hZGVyLmxvYWQocm9vdHMsIG5hbWVzcGFjZSwgbGFuZykpKTtcbiAgICBqc29uQXJyYXkuZm9yRWFjaCgoanNvbiwgaW5kZXgpID0+IHRoaXMuaGFuZGxlTmV3VHJhbnNsYXRpb25zKGpzb24sIGxhbmcsIGxvYWRMaXN0W2luZGV4XSwgdW5kZWZpbmVkKSlcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlTmV3VHJhbnNsYXRpb25zKGpzb246IFRyYW5zbGF0aW9ucywgbGFuZzogc3RyaW5nLCBuYW1lc3BhY2U6IHN0cmluZywgdmVyc2lvbj86IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IG1hcCA9IG5ldyBNYXAodGhpcy5fanNvbkNhY2hlKCkpO1xuICAgIGNvbnN0IGxhbmdNYXAgPSBuZXcgTWFwKHRoaXMuX2pzb25DYWNoZSgpLmdldChsYW5nKSk7XG4gICAgbGFuZ01hcC5zZXQobmFtZXNwYWNlLCBqc29uKTtcbiAgICBtYXAuc2V0KGxhbmcsIGxhbmdNYXApO1xuICAgIHRoaXMuX2pzb25DYWNoZS5zZXQobWFwKTtcblxuICAgIGNvbnN0IHZNYXAgPSBuZXcgTWFwKHRoaXMuX3ZlcnNpb25NYXAoKSk7XG4gICAgY29uc3QgdkxhbmdNYXAgPSBuZXcgTWFwKHRoaXMuX3ZlcnNpb25NYXAoKS5nZXQobGFuZykpO1xuICAgIHZMYW5nTWFwLnNldChuYW1lc3BhY2UsIHZlcnNpb24pO1xuICAgIHZNYXAuc2V0KGxhbmcsIHZMYW5nTWFwKTtcbiAgICB0aGlzLl92ZXJzaW9uTWFwLnNldCh2TWFwKTtcblxuICAgIC8vIEludmFsaWRhdGUgZm9ybWF0dGVyIGNhY2hlIGZvciB0aGlzIG5hbWVzcGFjZSAoY292ZXJzIHdpdGgvd2l0aG91dCB2ZXJzaW9uKVxuICAgIGNvbnN0IG5zS2V5ID0gYCR7bGFuZ306JHtuYW1lc3BhY2V9OmA7XG4gICAgdGhpcy5fZm9ybWF0dGVyQ2FjaGUuZGVsZXRlV2hlcmUoKGspID0+IChrIGFzIHVua25vd24gYXMgc3RyaW5nKS5zdGFydHNXaXRoKG5zS2V5KSk7XG5cbiAgICB0aGlzLl9taXNzaW5nS2V5Q2FjaGUuY2xlYXIoKTtcbiAgICBpZiAodGhpcy5kZWJ1Z0VuYWJsZWQpIHtcbiAgICAgIGNvbnN0IGtleUNvdW50ID0ganNvbiAmJiB0eXBlb2YganNvbiA9PT0gJ29iamVjdCcgPyBPYmplY3Qua2V5cyhqc29uKS5sZW5ndGggOiAwO1xuICAgICAgdGhpcy5sb2coYENhY2hlZCBuYW1lc3BhY2UgXCIke25hbWVzcGFjZX1cIiBmb3IgXCIke2xhbmd9XCIgKCR7a2V5Q291bnR9IHRvcC1sZXZlbCBrZXlzKS5gKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGhhc0pzb25DYWNoZVZhbHVlKGxhbmc6IHN0cmluZywgbmFtZXNwYWNlOiBzdHJpbmcsIHZlcnNpb24/OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBleGlzdHMgPSB0aGlzLl9qc29uQ2FjaGUoKS5nZXQobGFuZyk/LmdldChuYW1lc3BhY2UpICE9PSB1bmRlZmluZWQ7XG4gICAgaWYgKCFleGlzdHMpIHJldHVybiBmYWxzZTtcbiAgICBpZiAodmVyc2lvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCBzdG9yZWQgPSB0aGlzLl92ZXJzaW9uTWFwKCkuZ2V0KGxhbmcpPy5nZXQobmFtZXNwYWNlKTtcbiAgICAgIHJldHVybiBzdG9yZWQgPT09IHZlcnNpb247XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgYWRkUmVzb3VyY2VCdW5kbGUobGFuZzogc3RyaW5nLCBuYW1lc3BhY2U6IHN0cmluZywgYnVuZGxlOiBUcmFuc2xhdGlvbnMsIGRlZXAgPSB0cnVlLCBvdmVyd3JpdGUgPSB0cnVlKSB7XG4gICAgY29uc3QgbWFwID0gbmV3IE1hcCh0aGlzLl9qc29uQ2FjaGUoKSk7XG4gICAgY29uc3Qgb2xkTGFuZ01hcCA9IG1hcC5nZXQobGFuZyk7XG4gICAgY29uc3QgbGFuZ01hcCA9IG9sZExhbmdNYXAgPyBuZXcgTWFwKG1hcC5nZXQobGFuZykpIDogbmV3IE1hcDxzdHJpbmcsIFRyYW5zbGF0aW9ucz4oKTtcbiAgICBjb25zdCBleGlzdFRyYW5zbGF0aW9ucyA9IGxhbmdNYXAuZ2V0KG5hbWVzcGFjZSkgPz8ge307XG4gICAgbGV0IG1lcmdlZDogVHJhbnNsYXRpb25zO1xuICAgIGlmIChkZWVwKSB7XG4gICAgICBtZXJnZWQgPSBvdmVyd3JpdGVcbiAgICAgICAgPyBkZWVwTWVyZ2UoZXhpc3RUcmFuc2xhdGlvbnMsIGJ1bmRsZSlcbiAgICAgICAgOiBkZWVwTWVyZ2UoZXhpc3RUcmFuc2xhdGlvbnMsIGZpbHRlck5ld0tleXNEZWVwKGJ1bmRsZSwgZXhpc3RUcmFuc2xhdGlvbnMpKVxuICAgIH0gZWxzZSB7XG4gICAgICBtZXJnZWQgPSBvdmVyd3JpdGVcbiAgICAgICAgPyB7IC4uLmV4aXN0VHJhbnNsYXRpb25zLCAuLi5idW5kbGUgfVxuICAgICAgICA6IHsgLi4uYnVuZGxlIH1cbiAgICAgIGlmICghb3ZlcndyaXRlKSB7XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIGV4aXN0VHJhbnNsYXRpb25zKSB7XG4gICAgICAgICAgaWYgKCEoa2V5IGluIG1lcmdlZCkpIHtcbiAgICAgICAgICAgIG1lcmdlZFtrZXldID0gZXhpc3RUcmFuc2xhdGlvbnNba2V5XTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgbGFuZ01hcC5zZXQobmFtZXNwYWNlLCBtZXJnZWQpO1xuICAgIG1hcC5zZXQobGFuZywgbGFuZ01hcCk7XG4gICAgdGhpcy5fanNvbkNhY2hlLnNldChtYXApO1xuICB9XG5cbiAgYWRkUmVzb3VyY2VzKGxhbmc6IHN0cmluZywgbmFtZXNwYWNlOiBzdHJpbmcsIG9iajogVHJhbnNsYXRpb25zLCBvdmVyd3JpdGUgPSB0cnVlKSB7XG4gICAgdGhpcy5hZGRSZXNvdXJjZUJ1bmRsZShsYW5nLCBuYW1lc3BhY2UsIG9iaiwgZmFsc2UsIG92ZXJ3cml0ZSk7XG4gIH1cblxuICBhZGRSZXNvdXJjZShsYW5nOiBzdHJpbmcsIG5hbWVzcGFjZTogc3RyaW5nLCBrZXk6IHN0cmluZywgdmFsOiBzdHJpbmcsIG92ZXJ3cml0ZSA9IHRydWUpIHtcbiAgICB0aGlzLmFkZFJlc291cmNlcyhsYW5nLCBuYW1lc3BhY2UsIHsgW2tleV06IHZhbCB9LCBvdmVyd3JpdGUpO1xuICB9XG5cbiAgZ2V0QWxsQnVuZGxlKCk6IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIFJlY29yZDxzdHJpbmcsIGFueT4+PiB7XG4gICAgcmV0dXJuIHRoaXMuX2pzb25DYWNoZSgpXG4gIH1cblxuICBoYXNSZXNvdXJjZUJ1bmRsZShsYW5nOiBzdHJpbmcsIG5hbWVzcGFjZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhdGhpcy5fanNvbkNhY2hlKCkuZ2V0KGxhbmcpPy5oYXMobmFtZXNwYWNlKTtcbiAgfVxuXG4gIGdldFJlc291cmNlQnVuZGxlKGxhbmc6IHN0cmluZywgbmFtZXNwYWNlOiBzdHJpbmcpOiBUcmFuc2xhdGlvbnMgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9qc29uQ2FjaGUoKS5nZXQobGFuZyk/LmdldChuYW1lc3BhY2UpO1xuICB9XG5cbiAgcmVtb3ZlUmVzb3VyY2VCdW5kbGUobGFuZzogc3RyaW5nLCBuYW1lc3BhY2U6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IG1hcCA9IG5ldyBNYXAodGhpcy5fanNvbkNhY2hlKCkpO1xuICAgIGNvbnN0IGxhbmdNYXAgPSBuZXcgTWFwKG1hcC5nZXQobGFuZykpO1xuICAgIGxhbmdNYXAuZGVsZXRlKG5hbWVzcGFjZSlcbiAgICBtYXAuc2V0KGxhbmcsIGxhbmdNYXApO1xuICAgIHRoaXMuX2pzb25DYWNoZS5zZXQobWFwKTtcbiAgICAvLyBFdmljdCBhbGwgZm9ybWF0dGVyIGNhY2hlIGVudHJpZXMgdGhhdCBiZWxvbmcgdG8gdGhpcyBsYW5nOm5hbWVzcGFjZSAod2l0aCBvciB3aXRob3V0IHZlcnNpb24pXG4gICAgLy8gS2V5cyBhcmUgaW4gZm9ybSBgJHtuc0tleX06JHtrZXl9YCB3aGVyZSBuc0tleSBtYXkgaW5jbHVkZSB2ZXJzaW9uXG4gICAgY29uc3QgcHJlZml4ID0gYCR7bGFuZ306JHtuYW1lc3BhY2V9OmA7XG4gICAgdGhpcy5fZm9ybWF0dGVyQ2FjaGUuZGVsZXRlV2hlcmUoKGspID0+IChrIGFzIHVua25vd24gYXMgc3RyaW5nKS5zdGFydHNXaXRoKHByZWZpeCkpO1xuICAgIC8vIGFsc28gY2xlYXIgbWlzc2luZy1rZXkgZW50cmllcyBmb3IgdGhpcyBuYW1lc3BhY2VcbiAgICBmb3IgKGNvbnN0IGsgb2YgQXJyYXkuZnJvbSh0aGlzLl9taXNzaW5nS2V5Q2FjaGUpKSB7XG4gICAgICBpZiAoay5zdGFydHNXaXRoKHByZWZpeCkpIHRoaXMuX21pc3NpbmdLZXlDYWNoZS5kZWxldGUoayk7XG4gICAgfVxuICB9XG5cbiAgLyoqIENsZWFyIGV2ZXJ5dGhpbmc6IGRhdGEsIHZlcnNpb25zLCBmb3JtYXR0ZXJzLCBtaXNzaW5nIGtleXMsIGluZmxpZ2h0ICovXG4gIGNsZWFyQWxsKCk6IHZvaWQge1xuICAgIHRoaXMuX2pzb25DYWNoZS5zZXQobmV3IE1hcCgpKTtcbiAgICB0aGlzLl92ZXJzaW9uTWFwLnNldChuZXcgTWFwKCkpO1xuICAgIHRoaXMuX2Zvcm1hdHRlckNhY2hlLmNsZWFyKCk7XG4gICAgdGhpcy5fbWlzc2luZ0tleUNhY2hlLmNsZWFyKCk7XG4gICAgdGhpcy5faW5mbGlnaHQuY2xlYXIoKTtcbiAgICB0aGlzLl9pY3VDb21waWxlZENhY2hlLmNsZWFyKCk7XG4gIH1cblxuICAvKiogQ2xlYXIgYWxsIHJlc291cmNlcyBmb3IgYSBsYW5ndWFnZSAqL1xuICBjbGVhckxhbmcobGFuZzogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgbWFwID0gbmV3IE1hcCh0aGlzLl9qc29uQ2FjaGUoKSk7XG4gICAgbWFwLmRlbGV0ZShsYW5nKTtcbiAgICB0aGlzLl9qc29uQ2FjaGUuc2V0KG1hcCk7XG4gICAgY29uc3Qgdm1hcCA9IG5ldyBNYXAodGhpcy5fdmVyc2lvbk1hcCgpKTtcbiAgICB2bWFwLmRlbGV0ZShsYW5nKTtcbiAgICB0aGlzLl92ZXJzaW9uTWFwLnNldCh2bWFwKTtcbiAgICB0aGlzLl9mb3JtYXR0ZXJDYWNoZS5kZWxldGVXaGVyZSgoaykgPT4gKGsgYXMgdW5rbm93biBhcyBzdHJpbmcpLnN0YXJ0c1dpdGgoYCR7bGFuZ306YCkpO1xuICAgIGZvciAoY29uc3QgayBvZiBBcnJheS5mcm9tKHRoaXMuX21pc3NpbmdLZXlDYWNoZSkpIHtcbiAgICAgIGlmIChrLnN0YXJ0c1dpdGgoYCR7bGFuZ306YCkpIHRoaXMuX21pc3NpbmdLZXlDYWNoZS5kZWxldGUoayk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgayBvZiBBcnJheS5mcm9tKHRoaXMuX2ljdUNvbXBpbGVkQ2FjaGUua2V5cygpKSkge1xuICAgICAgaWYgKGsuZW5kc1dpdGgoYHwke2xhbmd9YCkpIHRoaXMuX2ljdUNvbXBpbGVkQ2FjaGUuZGVsZXRlKGspO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBDbGVhciBhIHNwZWNpZmljIG5hbWVzcGFjZSBmb3IgYSBsYW5ndWFnZSAqL1xuICBjbGVhck5hbWVzcGFjZShsYW5nOiBzdHJpbmcsIG5hbWVzcGFjZTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5yZW1vdmVSZXNvdXJjZUJ1bmRsZShsYW5nLCBuYW1lc3BhY2UpO1xuICB9XG5cbiAgZ2V0UmVzb3VyY2UobGFuZzogc3RyaW5nLCBuYW1lc3BhY2U6IHN0cmluZywga2V5OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiBnZXROZXN0ZWQodGhpcy5fanNvbkNhY2hlKCkuZ2V0KGxhbmcpPy5nZXQobmFtZXNwYWNlKSwga2V5KTtcbiAgfVxuXG4gIHByaXZhdGUgbG9nKG1lc3NhZ2U6IHN0cmluZywgLi4uZGV0YWlsczogdW5rbm93bltdKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmRlYnVnRW5hYmxlZCkgcmV0dXJuO1xuICAgIGlmIChkZXRhaWxzLmxlbmd0aCkge1xuICAgICAgY29uc29sZS5pbmZvKGBbbmd4LWF0b21pYy1pMThuXSAke21lc3NhZ2V9YCwgLi4uZGV0YWlscyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUuaW5mbyhgW25neC1hdG9taWMtaTE4bl0gJHttZXNzYWdlfWApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZXJyb3IobWVzc2FnZTogc3RyaW5nLCBlcnJvcjogdW5rbm93bik6IHZvaWQge1xuICAgIGlmICghdGhpcy5kZWJ1Z0VuYWJsZWQpIHJldHVybjtcbiAgICBjb25zb2xlLmVycm9yKGBbbmd4LWF0b21pYy1pMThuXSAke21lc3NhZ2V9YCwgZXJyb3IpO1xuICB9XG5cbiAgcHJpdmF0ZSB3YXJuKG1lc3NhZ2U6IHN0cmluZywgLi4uZGV0YWlsczogdW5rbm93bltdKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmRlYnVnRW5hYmxlZCkgcmV0dXJuO1xuICAgIGlmIChkZXRhaWxzLmxlbmd0aCkge1xuICAgICAgY29uc29sZS53YXJuKGBbbmd4LWF0b21pYy1pMThuXSAke21lc3NhZ2V9YCwgLi4uZGV0YWlscyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUud2FybihgW25neC1hdG9taWMtaTE4bl0gJHttZXNzYWdlfWApO1xuICAgIH1cbiAgfVxufVxuIl19
@@ -0,0 +1,35 @@
1
+ import { Directive, effect, ElementRef, inject, input } from '@angular/core';
2
+ import { TranslationService } from './translation.service';
3
+ import * as i0 from "@angular/core";
4
+ /** Binds translation keys to an element, updating text or attributes reactively. */
5
+ export class TranslationDirective {
6
+ selfElm = inject(ElementRef).nativeElement;
7
+ service = inject(TranslationService);
8
+ /** Translation key resolved for the host element. */
9
+ t = input('');
10
+ /** Optional interpolation parameters passed to the translation formatter. */
11
+ tParams = input(undefined);
12
+ /** Attribute name to receive the translated value instead of textContent. */
13
+ tAttr = input('');
14
+ constructor() {
15
+ effect(() => {
16
+ const value = this.service.t(this.t(), this.tParams());
17
+ if (this.tAttr()) {
18
+ this.selfElm.setAttribute(this.tAttr(), value);
19
+ }
20
+ else {
21
+ this.selfElm.textContent = value;
22
+ }
23
+ });
24
+ }
25
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
26
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.13", type: TranslationDirective, isStandalone: true, selector: "[t]", inputs: { t: { classPropertyName: "t", publicName: "t", isSignal: true, isRequired: false, transformFunction: null }, tParams: { classPropertyName: "tParams", publicName: "tParams", isSignal: true, isRequired: false, transformFunction: null }, tAttr: { classPropertyName: "tAttr", publicName: "tAttr", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
27
+ }
28
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationDirective, decorators: [{
29
+ type: Directive,
30
+ args: [{
31
+ selector: '[t]',
32
+ standalone: true
33
+ }]
34
+ }], ctorParameters: () => [] });
35
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNsYXRpb24uZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWF0b21pYy1pMThuL3NyYy9saWIvdHJhbnNsYXRpb24uZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzdFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDOztBQU8zRCxvRkFBb0Y7QUFDcEYsTUFBTSxPQUFPLG9CQUFvQjtJQUN2QixPQUFPLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLGFBQTRCLENBQUM7SUFDMUQsT0FBTyxHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQzdDLHFEQUFxRDtJQUM1QyxDQUFDLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZCLDZFQUE2RTtJQUNwRSxPQUFPLEdBQUcsS0FBSyxDQUFxQixTQUFTLENBQUMsQ0FBQztJQUN4RCw2RUFBNkU7SUFDcEUsS0FBSyxHQUFHLEtBQUssQ0FBUyxFQUFFLENBQUMsQ0FBQztJQUNuQztRQUNFLE1BQU0sQ0FBQyxHQUFHLEVBQUU7WUFDVixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFDdkQsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQztnQkFDakIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ2pELENBQUM7aUJBQU0sQ0FBQztnQkFDTixJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUM7WUFDbkMsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzt3R0FsQlUsb0JBQW9COzRGQUFwQixvQkFBb0I7OzRGQUFwQixvQkFBb0I7a0JBTGhDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLEtBQUs7b0JBQ2YsVUFBVSxFQUFFLElBQUk7aUJBQ2pCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGlyZWN0aXZlLCBlZmZlY3QsIEVsZW1lbnRSZWYsIGluamVjdCwgaW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFRyYW5zbGF0aW9uU2VydmljZSB9IGZyb20gJy4vdHJhbnNsYXRpb24uc2VydmljZSc7XG5pbXBvcnQgeyBQYXJhbXMgfSBmcm9tICcuL3RyYW5zbGF0ZS50eXBlJztcblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW3RdJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZVxufSlcbi8qKiBCaW5kcyB0cmFuc2xhdGlvbiBrZXlzIHRvIGFuIGVsZW1lbnQsIHVwZGF0aW5nIHRleHQgb3IgYXR0cmlidXRlcyByZWFjdGl2ZWx5LiAqL1xuZXhwb3J0IGNsYXNzIFRyYW5zbGF0aW9uRGlyZWN0aXZlIHtcbiAgcHJpdmF0ZSBzZWxmRWxtID0gaW5qZWN0KEVsZW1lbnRSZWYpLm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnQ7XG4gIHByaXZhdGUgc2VydmljZSA9IGluamVjdChUcmFuc2xhdGlvblNlcnZpY2UpO1xuICAvKiogVHJhbnNsYXRpb24ga2V5IHJlc29sdmVkIGZvciB0aGUgaG9zdCBlbGVtZW50LiAqL1xuICByZWFkb25seSB0ID0gaW5wdXQoJycpO1xuICAvKiogT3B0aW9uYWwgaW50ZXJwb2xhdGlvbiBwYXJhbWV0ZXJzIHBhc3NlZCB0byB0aGUgdHJhbnNsYXRpb24gZm9ybWF0dGVyLiAqL1xuICByZWFkb25seSB0UGFyYW1zID0gaW5wdXQ8UGFyYW1zIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICAvKiogQXR0cmlidXRlIG5hbWUgdG8gcmVjZWl2ZSB0aGUgdHJhbnNsYXRlZCB2YWx1ZSBpbnN0ZWFkIG9mIHRleHRDb250ZW50LiAqL1xuICByZWFkb25seSB0QXR0ciA9IGlucHV0PHN0cmluZz4oJycpO1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBlZmZlY3QoKCkgPT4ge1xuICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLnNlcnZpY2UudCh0aGlzLnQoKSwgdGhpcy50UGFyYW1zKCkpO1xuICAgICAgaWYgKHRoaXMudEF0dHIoKSkge1xuICAgICAgICB0aGlzLnNlbGZFbG0uc2V0QXR0cmlidXRlKHRoaXMudEF0dHIoKSwgdmFsdWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5zZWxmRWxtLnRleHRDb250ZW50ID0gdmFsdWU7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,44 @@
1
+ import { defaultConfig } from './translate.provider';
2
+ import { TempToken } from "./translate.type";
3
+ import { firstValueFrom } from "rxjs";
4
+ import { detectBuildVersion, tempToArray } from "./translate.util";
5
+ export class HttpTranslationLoader {
6
+ http;
7
+ option;
8
+ pathTemplates;
9
+ pathTemplateCache;
10
+ constructor(http, option = {}, pathTemplates) {
11
+ this.http = http;
12
+ this.option = option;
13
+ this.pathTemplates = pathTemplates;
14
+ }
15
+ async load(i18nRoots, namespace, lang) {
16
+ const roots = tempToArray(i18nRoots) ?? [];
17
+ const baseUrl = this.option.baseUrl ?? '/assets';
18
+ const safeBaseUrl = (/^https?:\/\//i.test(baseUrl)
19
+ ? baseUrl
20
+ : (baseUrl.startsWith('/') ? baseUrl : '/' + baseUrl)).replace(/[\\/]+$/, '');
21
+ const tempArray = tempToArray(this.pathTemplates);
22
+ const pathTemps = this.pathTemplateCache ? [this.pathTemplateCache, ...(tempArray ?? []).filter(t => t !== this.pathTemplateCache)] : (tempArray ?? defaultConfig.pathTemplates);
23
+ for (const root of roots) {
24
+ for (const temp of pathTemps) {
25
+ let url = `${safeBaseUrl}/${temp.replace(TempToken.Root, root).replace(TempToken.Lang, lang).replace(TempToken.Namespace, namespace)}`;
26
+ const v = detectBuildVersion();
27
+ if (v) {
28
+ url += (url.includes('?') ? '&' : '?') + `v=${encodeURIComponent(v)}`;
29
+ }
30
+ try {
31
+ const json = await firstValueFrom(this.http.get(url));
32
+ if (!this.pathTemplateCache)
33
+ this.pathTemplateCache = temp;
34
+ return json;
35
+ }
36
+ catch {
37
+ /* ignore */
38
+ }
39
+ }
40
+ }
41
+ throw new Error(`[i18n] ${namespace}.json for ${lang} not found in any i18nRoot`);
42
+ }
43
+ }
44
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNsYXRpb24ubG9hZGVyLmNzci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1hdG9taWMtaTE4bi9zcmMvbGliL3RyYW5zbGF0aW9uLmxvYWRlci5jc3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRXJELE9BQU8sRUFBcUIsU0FBUyxFQUFtQyxNQUFNLGtCQUFrQixDQUFDO0FBQ2pHLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLFdBQVcsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRW5FLE1BQU0sT0FBTyxxQkFBcUI7SUFHYjtJQUNBO0lBQ0E7SUFKWCxpQkFBaUIsQ0FBVTtJQUNuQyxZQUNtQixJQUFnQixFQUNoQixTQUE0QixFQUFFLEVBQzlCLGFBQWdDO1FBRmhDLFNBQUksR0FBSixJQUFJLENBQVk7UUFDaEIsV0FBTSxHQUFOLE1BQU0sQ0FBd0I7UUFDOUIsa0JBQWEsR0FBYixhQUFhLENBQW1CO0lBQy9DLENBQUM7SUFFTCxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQW1CLEVBQUUsU0FBaUIsRUFBRSxJQUFZO1FBQzdELE1BQU0sS0FBSyxHQUFHLFdBQVcsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDM0MsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLElBQUksU0FBUyxDQUFDO1FBQ2pELE1BQU0sV0FBVyxHQUFHLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7WUFDaEQsQ0FBQyxDQUFDLE9BQU87WUFDVCxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDaEYsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQTtRQUNqRCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLEdBQUcsQ0FBQyxTQUFTLElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxJQUFJLGFBQWEsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNqTCxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ3pCLEtBQUssTUFBTSxJQUFJLElBQUksU0FBUyxFQUFFLENBQUM7Z0JBQzdCLElBQUksR0FBRyxHQUFHLEdBQUcsV0FBVyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsRUFBRSxDQUFDO2dCQUN2SSxNQUFNLENBQUMsR0FBRyxrQkFBa0IsRUFBRSxDQUFDO2dCQUMvQixJQUFJLENBQUMsRUFBRSxDQUFDO29CQUNOLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsS0FBSyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUN4RSxDQUFDO2dCQUNELElBQUksQ0FBQztvQkFDSCxNQUFNLElBQUksR0FBRyxNQUFNLGNBQWMsQ0FDL0IsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQWUsR0FBRyxDQUFDLENBQ2pDLENBQUM7b0JBQ0YsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUI7d0JBQUUsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQztvQkFDM0QsT0FBTyxJQUFJLENBQUM7Z0JBQ2QsQ0FBQztnQkFBQyxNQUFNLENBQUM7b0JBQ1AsYUFBYTtnQkFDZixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLFVBQVUsU0FBUyxhQUFhLElBQUksNEJBQTRCLENBQUMsQ0FBQztJQUNwRixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBkZWZhdWx0Q29uZmlnIH0gZnJvbSAnLi90cmFuc2xhdGUucHJvdmlkZXInO1xuaW1wb3J0IHsgSHR0cENsaWVudCB9IGZyb20gXCJAYW5ndWxhci9jb21tb24vaHR0cFwiO1xuaW1wb3J0IHsgSHR0cExvYWRlck9wdGlvbnMsIFRlbXBUb2tlbiwgVHJhbnNsYXRpb25Mb2FkZXIsIFRyYW5zbGF0aW9ucyB9IGZyb20gXCIuL3RyYW5zbGF0ZS50eXBlXCI7XG5pbXBvcnQgeyBmaXJzdFZhbHVlRnJvbSB9IGZyb20gXCJyeGpzXCI7XG5pbXBvcnQgeyBkZXRlY3RCdWlsZFZlcnNpb24sIHRlbXBUb0FycmF5IH0gZnJvbSBcIi4vdHJhbnNsYXRlLnV0aWxcIjtcblxuZXhwb3J0IGNsYXNzIEh0dHBUcmFuc2xhdGlvbkxvYWRlciBpbXBsZW1lbnRzIFRyYW5zbGF0aW9uTG9hZGVyIHtcbiAgcHJpdmF0ZSBwYXRoVGVtcGxhdGVDYWNoZT86IHN0cmluZztcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBodHRwOiBIdHRwQ2xpZW50LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgb3B0aW9uOiBIdHRwTG9hZGVyT3B0aW9ucyA9IHt9LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcGF0aFRlbXBsYXRlczogc3RyaW5nW10gfCBzdHJpbmcsXG4gICkgeyB9XG5cbiAgYXN5bmMgbG9hZChpMThuUm9vdHM6IHN0cmluZ1tdLCBuYW1lc3BhY2U6IHN0cmluZywgbGFuZzogc3RyaW5nKTogUHJvbWlzZTxUcmFuc2xhdGlvbnM+IHtcbiAgICBjb25zdCByb290cyA9IHRlbXBUb0FycmF5KGkxOG5Sb290cykgPz8gW107XG4gICAgY29uc3QgYmFzZVVybCA9IHRoaXMub3B0aW9uLmJhc2VVcmwgPz8gJy9hc3NldHMnO1xuICAgIGNvbnN0IHNhZmVCYXNlVXJsID0gKC9eaHR0cHM/OlxcL1xcLy9pLnRlc3QoYmFzZVVybClcbiAgICAgID8gYmFzZVVybFxuICAgICAgOiAoYmFzZVVybC5zdGFydHNXaXRoKCcvJykgPyBiYXNlVXJsIDogJy8nICsgYmFzZVVybCkpLnJlcGxhY2UoL1tcXFxcL10rJC8sICcnKTtcbiAgICBjb25zdCB0ZW1wQXJyYXkgPSB0ZW1wVG9BcnJheSh0aGlzLnBhdGhUZW1wbGF0ZXMpXG4gICAgY29uc3QgcGF0aFRlbXBzID0gdGhpcy5wYXRoVGVtcGxhdGVDYWNoZSA/IFt0aGlzLnBhdGhUZW1wbGF0ZUNhY2hlLCAuLi4odGVtcEFycmF5ID8/IFtdKS5maWx0ZXIodCA9PiB0ICE9PSB0aGlzLnBhdGhUZW1wbGF0ZUNhY2hlKV0gOiAodGVtcEFycmF5ID8/IGRlZmF1bHRDb25maWcucGF0aFRlbXBsYXRlcyk7XG4gICAgZm9yIChjb25zdCByb290IG9mIHJvb3RzKSB7XG4gICAgICBmb3IgKGNvbnN0IHRlbXAgb2YgcGF0aFRlbXBzKSB7XG4gICAgICAgIGxldCB1cmwgPSBgJHtzYWZlQmFzZVVybH0vJHt0ZW1wLnJlcGxhY2UoVGVtcFRva2VuLlJvb3QsIHJvb3QpLnJlcGxhY2UoVGVtcFRva2VuLkxhbmcsIGxhbmcpLnJlcGxhY2UoVGVtcFRva2VuLk5hbWVzcGFjZSwgbmFtZXNwYWNlKX1gO1xuICAgICAgICBjb25zdCB2ID0gZGV0ZWN0QnVpbGRWZXJzaW9uKCk7XG4gICAgICAgIGlmICh2KSB7XG4gICAgICAgICAgdXJsICs9ICh1cmwuaW5jbHVkZXMoJz8nKSA/ICcmJyA6ICc/JykgKyBgdj0ke2VuY29kZVVSSUNvbXBvbmVudCh2KX1gO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QganNvbiA9IGF3YWl0IGZpcnN0VmFsdWVGcm9tKFxuICAgICAgICAgICAgdGhpcy5odHRwLmdldDxUcmFuc2xhdGlvbnM+KHVybClcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmICghdGhpcy5wYXRoVGVtcGxhdGVDYWNoZSkgdGhpcy5wYXRoVGVtcGxhdGVDYWNoZSA9IHRlbXA7XG4gICAgICAgICAgcmV0dXJuIGpzb247XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIC8qIGlnbm9yZSAgKi9cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYFtpMThuXSAke25hbWVzcGFjZX0uanNvbiBmb3IgJHtsYW5nfSBub3QgZm91bmQgaW4gYW55IGkxOG5Sb290YCk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,89 @@
1
+ import { defaultConfig } from './translate.provider';
2
+ import { TempToken as t, } from './translate.type';
3
+ import { stripLeadingSep, tempToArray } from './translate.util';
4
+ /** File-system backed loader used during SSR to read translation JSON from disk. */
5
+ export class FsTranslationLoader {
6
+ fsOptions;
7
+ pathTemplates;
8
+ customFs;
9
+ cache = new Map();
10
+ /**
11
+ * @param customFs Optional fs-like abstraction injected explicitly (tests or adapters).
12
+ */
13
+ constructor(fsOptions = {}, pathTemplates, customFs) {
14
+ this.fsOptions = fsOptions;
15
+ this.pathTemplates = pathTemplates;
16
+ this.customFs = customFs;
17
+ }
18
+ async load(i18nRoots, namespace, lang) {
19
+ const roots = (Array.isArray(i18nRoots) ? i18nRoots : [i18nRoots]).map(stripLeadingSep);
20
+ const pathMod = await this.importSafely('node:path');
21
+ const fsImported = await this.importSafely('node:fs');
22
+ const fsLike = this.pickFs(this.customFs) ?? this.pickFs(this.fsOptions.fsModule) ?? this.pickFs(fsImported);
23
+ const nodeProcess = globalThis.process;
24
+ const baseDir = this.fsOptions.baseDir ?? (nodeProcess?.cwd?.() ?? '/');
25
+ const assetPathRaw = this.fsOptions.assetPath ?? 'dist/browser/assets';
26
+ const assetPath = stripLeadingSep(assetPathRaw);
27
+ const templates = tempToArray(this.pathTemplates) ??
28
+ tempToArray(defaultConfig.pathTemplates);
29
+ for (const root of roots) {
30
+ const candidatePaths = this.fsOptions.resolvePaths?.({
31
+ baseDir,
32
+ assetPath,
33
+ root,
34
+ lang,
35
+ namespace,
36
+ }) ??
37
+ templates.map((temp) => this.safeJoin(pathMod, baseDir, assetPath, temp.replace(t.Root, root).replace(t.Lang, lang).replace(t.Namespace, namespace)));
38
+ for (const absolutePath of candidatePaths) {
39
+ try {
40
+ if (!fsLike?.statSync || !fsLike?.readFileSync)
41
+ continue;
42
+ const stat = fsLike.statSync(absolutePath);
43
+ const mtimeMs = typeof stat.mtimeMs === 'number'
44
+ ? stat.mtimeMs
45
+ : stat.mtime?.getTime?.() ?? 0;
46
+ const size = typeof stat.size === 'number' ? stat.size : 0;
47
+ const sign = (mtimeMs | 0) * 1000003 + (size | 0);
48
+ const cached = this.cache.get(absolutePath);
49
+ if (cached && cached.mtimeMs === sign) {
50
+ return cached.data;
51
+ }
52
+ const raw = fsLike.readFileSync(absolutePath, 'utf8');
53
+ const json = JSON.parse(raw);
54
+ this.cache.set(absolutePath, { mtimeMs: sign, data: json });
55
+ return json;
56
+ }
57
+ catch {
58
+ // Continue probing other candidate files until a match is found.
59
+ }
60
+ }
61
+ }
62
+ throw new Error(`[SSR i18n] ${namespace}.json for ${lang} not found in any i18nRoot`);
63
+ }
64
+ /** Attempts to import a Node built-in without throwing when unavailable (e.g. CSR). */
65
+ async importSafely(specifier) {
66
+ const nodeProcess = globalThis.process;
67
+ const isNode = !!nodeProcess?.versions?.node;
68
+ if (!isNode)
69
+ return undefined;
70
+ try {
71
+ const importer = new Function('s', 'return import(s)');
72
+ return await importer(specifier);
73
+ }
74
+ catch {
75
+ return undefined;
76
+ }
77
+ }
78
+ pickFs(x) {
79
+ return x && typeof x.readFileSync === 'function' && typeof x.statSync === 'function'
80
+ ? x
81
+ : undefined;
82
+ }
83
+ safeJoin(pathMod, ...parts) {
84
+ return (pathMod?.join ??
85
+ pathMod?.default?.join ??
86
+ ((...parts) => parts.join('/')))(...parts);
87
+ }
88
+ }
89
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNsYXRpb24ubG9hZGVyLnNzci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1hdG9taWMtaTE4bi9zcmMvbGliL3RyYW5zbGF0aW9uLmxvYWRlci5zc3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3JELE9BQU8sRUFFTCxTQUFTLElBQUksQ0FBQyxHQUtmLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUFFLGVBQWUsRUFBRSxXQUFXLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUVoRSxvRkFBb0Y7QUFDcEYsTUFBTSxPQUFPLG1CQUFtQjtJQU1WO0lBQXlDO0lBQTBDO0lBTC9GLEtBQUssR0FBRyxJQUFJLEdBQUcsRUFBc0IsQ0FBQztJQUU5Qzs7T0FFRztJQUNILFlBQW9CLFlBQTZCLEVBQUUsRUFBVSxhQUFnQyxFQUFVLFFBQXVCO1FBQTFHLGNBQVMsR0FBVCxTQUFTLENBQXNCO1FBQVUsa0JBQWEsR0FBYixhQUFhLENBQW1CO1FBQVUsYUFBUSxHQUFSLFFBQVEsQ0FBZTtJQUFJLENBQUM7SUFFbkksS0FBSyxDQUFDLElBQUksQ0FBQyxTQUE0QixFQUFFLFNBQWlCLEVBQUUsSUFBWTtRQUN0RSxNQUFNLEtBQUssR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUV4RixNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDckQsTUFBTSxVQUFVLEdBQUcsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3RELE1BQU0sTUFBTSxHQUNWLElBQUksQ0FB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QUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDO0lBQ3RELENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGRlZmF1bHRDb25maWcgfSBmcm9tICcuL3RyYW5zbGF0ZS5wcm92aWRlcic7XG5pbXBvcnQge1xuICBGc01vZHVsZUxpa2UsXG4gIFRlbXBUb2tlbiBhcyB0LFxuICB0eXBlIENhY2hlRW50cnksXG4gIHR5cGUgRnNMb2FkZXJPcHRpb25zLFxuICB0eXBlIFRyYW5zbGF0aW9uTG9hZGVyLFxuICB0eXBlIFRyYW5zbGF0aW9ucyxcbn0gZnJvbSAnLi90cmFuc2xhdGUudHlwZSc7XG5pbXBvcnQgeyBzdHJpcExlYWRpbmdTZXAsIHRlbXBUb0FycmF5IH0gZnJvbSAnLi90cmFuc2xhdGUudXRpbCc7XG5cbi8qKiBGaWxlLXN5c3RlbSBiYWNrZWQgbG9hZGVyIHVzZWQgZHVyaW5nIFNTUiB0byByZWFkIHRyYW5zbGF0aW9uIEpTT04gZnJvbSBkaXNrLiAqL1xuZXhwb3J0IGNsYXNzIEZzVHJhbnNsYXRpb25Mb2FkZXIgaW1wbGVtZW50cyBUcmFuc2xhdGlvbkxvYWRlciB7XG4gIHByaXZhdGUgY2FjaGUgPSBuZXcgTWFwPHN0cmluZywgQ2FjaGVFbnRyeT4oKTtcblxuICAvKipcbiAgICogQHBhcmFtIGN1c3RvbUZzICBPcHRpb25hbCBmcy1saWtlIGFic3RyYWN0aW9uIGluamVjdGVkIGV4cGxpY2l0bHkgKHRlc3RzIG9yIGFkYXB0ZXJzKS5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZnNPcHRpb25zOiBGc0xvYWRlck9wdGlvbnMgPSB7fSwgcHJpdmF0ZSBwYXRoVGVtcGxhdGVzOiBzdHJpbmdbXSB8IHN0cmluZywgcHJpdmF0ZSBjdXN0b21Gcz86IEZzTW9kdWxlTGlrZSkgeyB9XG5cbiAgYXN5bmMgbG9hZChpMThuUm9vdHM6IHN0cmluZ1tdIHwgc3RyaW5nLCBuYW1lc3BhY2U6IHN0cmluZywgbGFuZzogc3RyaW5nKTogUHJvbWlzZTxUcmFuc2xhdGlvbnM+IHtcbiAgICBjb25zdCByb290cyA9IChBcnJheS5pc0FycmF5KGkxOG5Sb290cykgPyBpMThuUm9vdHMgOiBbaTE4blJvb3RzXSkubWFwKHN0cmlwTGVhZGluZ1NlcCk7XG5cbiAgICBjb25zdCBwYXRoTW9kID0gYXdhaXQgdGhpcy5pbXBvcnRTYWZlbHkoJ25vZGU6cGF0aCcpO1xuICAgIGNvbnN0IGZzSW1wb3J0ZWQgPSBhd2FpdCB0aGlzLmltcG9ydFNhZmVseSgnbm9kZTpmcycpO1xuICAgIGNvbnN0IGZzTGlrZTogRnNNb2R1bGVMaWtlIHwgdW5kZWZpbmVkID1cbiAgICAgIHRoaXMucGlja0ZzKHRoaXMuY3VzdG9tRnMpID8/IHRoaXMucGlja0ZzKHRoaXMuZnNPcHRpb25zLmZzTW9kdWxlKSA/PyB0aGlzLnBpY2tGcyhmc0ltcG9ydGVkKTtcblxuICAgIGNvbnN0IG5vZGVQcm9jZXNzID0gKGdsb2JhbFRoaXMgYXMgYW55KS5wcm9jZXNzIGFzIHsgY3dkPzogKCkgPT4gc3RyaW5nIH0gfCB1bmRlZmluZWQ7XG4gICAgY29uc3QgYmFzZURpciA9IHRoaXMuZnNPcHRpb25zLmJhc2VEaXIgPz8gKG5vZGVQcm9jZXNzPy5jd2Q/LigpID8/ICcvJyk7XG4gICAgY29uc3QgYXNzZXRQYXRoUmF3ID0gdGhpcy5mc09wdGlvbnMuYXNzZXRQYXRoID8/ICdkaXN0L2Jyb3dzZXIvYXNzZXRzJztcbiAgICBjb25zdCBhc3NldFBhdGggPSBzdHJpcExlYWRpbmdTZXAoYXNzZXRQYXRoUmF3KTtcblxuICAgIGNvbnN0IHRlbXBsYXRlcyA9XG4gICAgICB0ZW1wVG9BcnJheSh0aGlzLnBhdGhUZW1wbGF0ZXMpID8/XG4gICAgICB0ZW1wVG9BcnJheShkZWZhdWx0Q29uZmlnLnBhdGhUZW1wbGF0ZXMpIGFzIHN0cmluZ1tdO1xuXG4gICAgZm9yIChjb25zdCByb290IG9mIHJvb3RzKSB7XG4gICAgICBjb25zdCBjYW5kaWRhdGVQYXRocyA9XG4gICAgICAgIHRoaXMuZnNPcHRpb25zLnJlc29sdmVQYXRocz8uKHtcbiAgICAgICAgICBiYXNlRGlyLFxuICAgICAgICAgIGFzc2V0UGF0aCxcbiAgICAgICAgICByb290LFxuICAgICAgICAgIGxhbmcsXG4gICAgICAgICAgbmFtZXNwYWNlLFxuICAgICAgICB9KSA/P1xuICAgICAgICB0ZW1wbGF0ZXMubWFwKCh0ZW1wKSA9PlxuICAgICAgICAgIHRoaXMuc2FmZUpvaW4oXG4gICAgICAgICAgICBwYXRoTW9kLFxuICAgICAgICAgICAgYmFzZURpcixcbiAgICAgICAgICAgIGFzc2V0UGF0aCxcbiAgICAgICAgICAgIHRlbXAucmVwbGFjZSh0LlJvb3QsIHJvb3QpLnJlcGxhY2UodC5MYW5nLCBsYW5nKS5yZXBsYWNlKHQuTmFtZXNwYWNlLCBuYW1lc3BhY2UpLFxuICAgICAgICAgICksXG4gICAgICAgICk7XG5cbiAgICAgIGZvciAoY29uc3QgYWJzb2x1dGVQYXRoIG9mIGNhbmRpZGF0ZVBhdGhzKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgaWYgKCFmc0xpa2U/LnN0YXRTeW5jIHx8ICFmc0xpa2U/LnJlYWRGaWxlU3luYykgY29udGludWU7XG5cbiAgICAgICAgICBjb25zdCBzdGF0ID0gZnNMaWtlLnN0YXRTeW5jKGFic29sdXRlUGF0aCk7XG4gICAgICAgICAgY29uc3QgbXRpbWVNcyA9XG4gICAgICAgICAgICB0eXBlb2Ygc3RhdC5tdGltZU1zID09PSAnbnVtYmVyJ1xuICAgICAgICAgICAgICA/IHN0YXQubXRpbWVNc1xuICAgICAgICAgICAgICA6IHN0YXQubXRpbWU/LmdldFRpbWU/LigpID8/IDA7XG4gICAgICAgICAgY29uc3Qgc2l6ZSA9IHR5cGVvZiBzdGF0LnNpemUgPT09ICdudW1iZXInID8gc3RhdC5zaXplIDogMDtcbiAgICAgICAgICBjb25zdCBzaWduID0gKG10aW1lTXMgfCAwKSAqIDEwMDAwMDMgKyAoc2l6ZSB8IDApO1xuXG4gICAgICAgICAgY29uc3QgY2FjaGVkID0gdGhpcy5jYWNoZS5nZXQoYWJzb2x1dGVQYXRoKTtcbiAgICAgICAgICBpZiAoY2FjaGVkICYmIGNhY2hlZC5tdGltZU1zID09PSBzaWduKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkLmRhdGE7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgcmF3ID0gZnNMaWtlLnJlYWRGaWxlU3luYyhhYnNvbHV0ZVBhdGgsICd1dGY4Jyk7XG4gICAgICAgICAgY29uc3QganNvbiA9IEpTT04ucGFyc2UocmF3KSBhcyBUcmFuc2xhdGlvbnM7XG5cbiAgICAgICAgICB0aGlzLmNhY2hlLnNldChhYnNvbHV0ZVBhdGgsIHsgbXRpbWVNczogc2lnbiwgZGF0YToganNvbiB9KTtcbiAgICAgICAgICByZXR1cm4ganNvbjtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgLy8gQ29udGludWUgcHJvYmluZyBvdGhlciBjYW5kaWRhdGUgZmlsZXMgdW50aWwgYSBtYXRjaCBpcyBmb3VuZC5cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgW1NTUiBpMThuXSAke25hbWVzcGFjZX0uanNvbiBmb3IgJHtsYW5nfSBub3QgZm91bmQgaW4gYW55IGkxOG5Sb290YCk7XG4gIH1cblxuICAvKiogQXR0ZW1wdHMgdG8gaW1wb3J0IGEgTm9kZSBidWlsdC1pbiB3aXRob3V0IHRocm93aW5nIHdoZW4gdW5hdmFpbGFibGUgKGUuZy4gQ1NSKS4gKi9cbiAgcHJpdmF0ZSBhc3luYyBpbXBvcnRTYWZlbHkoc3BlY2lmaWVyOiBzdHJpbmcpOiBQcm9taXNlPGFueSB8IHVuZGVmaW5lZD4ge1xuICAgIGNvbnN0IG5vZGVQcm9jZXNzID0gKGdsb2JhbFRoaXMgYXMgYW55KS5wcm9jZXNzIGFzIHsgdmVyc2lvbnM/OiB7IG5vZGU/OiBzdHJpbmcgfSB9IHwgdW5kZWZpbmVkO1xuICAgIGNvbnN0IGlzTm9kZSA9ICEhbm9kZVByb2Nlc3M/LnZlcnNpb25zPy5ub2RlO1xuICAgIGlmICghaXNOb2RlKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBpbXBvcnRlciA9IG5ldyBGdW5jdGlvbigncycsICdyZXR1cm4gaW1wb3J0KHMpJyk7XG4gICAgICByZXR1cm4gYXdhaXQgaW1wb3J0ZXIoc3BlY2lmaWVyKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBwaWNrRnMoeDogYW55KTogRnNNb2R1bGVMaWtlIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4geCAmJiB0eXBlb2YgeC5yZWFkRmlsZVN5bmMgPT09ICdmdW5jdGlvbicgJiYgdHlwZW9mIHguc3RhdFN5bmMgPT09ICdmdW5jdGlvbidcbiAgICAgID8gKHggYXMgRnNNb2R1bGVMaWtlKVxuICAgICAgOiB1bmRlZmluZWQ7XG4gIH1cblxuICBwcml2YXRlIHNhZmVKb2luKHBhdGhNb2Q6IGFueSwgLi4ucGFydHM6IGFueVtdKTogc3RyaW5nIHtcbiAgICByZXR1cm4gKHBhdGhNb2Q/LmpvaW4gPz9cbiAgICAgIHBhdGhNb2Q/LmRlZmF1bHQ/LmpvaW4gPz9cbiAgICAgICgoLi4ucGFydHM6IGFueVtdKSA9PiBwYXJ0cy5qb2luKCcvJykpKSguLi5wYXJ0cyk7XG4gIH1cbn1cbiJdfQ==