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.
- package/README.md +24 -0
- package/esm2022/lib/FIFO.model.mjs +64 -0
- package/esm2022/lib/translate.pipe.mjs +18 -0
- package/esm2022/lib/translate.provider.mjs +121 -0
- package/esm2022/lib/translate.token.mjs +15 -0
- package/esm2022/lib/translate.type.mjs +10 -0
- package/esm2022/lib/translate.util.mjs +245 -0
- package/esm2022/lib/translation-core.service.mjs +312 -0
- package/esm2022/lib/translation.directive.mjs +35 -0
- package/esm2022/lib/translation.loader.csr.mjs +44 -0
- package/esm2022/lib/translation.loader.ssr.mjs +89 -0
- package/esm2022/lib/translation.service.mjs +165 -0
- package/esm2022/ngx-atomic-i18n.mjs +5 -0
- package/esm2022/public-api.mjs +15 -0
- package/fesm2022/ngx-atomic-i18n.mjs +1099 -0
- package/fesm2022/ngx-atomic-i18n.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/FIFO.model.d.ts +21 -0
- package/lib/translate.pipe.d.ts +10 -0
- package/lib/translate.provider.d.ts +17 -0
- package/lib/translate.token.d.ts +15 -0
- package/lib/translate.type.d.ts +103 -0
- package/lib/translate.util.d.ts +28 -0
- package/lib/translation-core.service.d.ts +55 -0
- package/lib/translation.directive.d.ts +15 -0
- package/lib/translation.loader.csr.d.ts +10 -0
- package/lib/translation.loader.ssr.d.ts +17 -0
- package/lib/translation.service.d.ts +60 -0
- package/package.json +48 -0
- package/public-api.d.ts +11 -0
|
@@ -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==
|