aril 2.0.1-dev.2 → 2.0.1-dev.4
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/boot/bridge/src/mfe-bridge.d.ts +33 -0
- package/esm2022/boot/bridge/src/mfe-bridge.mjs +18 -1
- package/esm2022/boot/mfe/src/bootstrap.mjs +49 -5
- package/esm2022/theme/layout/service/breadcrumb-publisher.service.mjs +12 -4
- package/esm2022/theme/layout/service/interfaces/interfaces.mjs +1 -1
- package/esm2022/theme/layout/service/selection-group.service.mjs +151 -21
- package/fesm2022/aril-boot-bridge.mjs +17 -0
- package/fesm2022/aril-boot-bridge.mjs.map +1 -1
- package/fesm2022/{aril-boot-mfe-app.component-a34GeuUv.mjs → aril-boot-mfe-app.component-oxzMhRXe.mjs} +2 -2
- package/fesm2022/{aril-boot-mfe-app.component-a34GeuUv.mjs.map → aril-boot-mfe-app.component-oxzMhRXe.mjs.map} +1 -1
- package/fesm2022/{aril-boot-mfe-aril-boot-mfe-KFO_X7yR.mjs → aril-boot-mfe-aril-boot-mfe-CKOM61xb.mjs} +50 -6
- package/fesm2022/aril-boot-mfe-aril-boot-mfe-CKOM61xb.mjs.map +1 -0
- package/fesm2022/aril-boot-mfe.mjs +1 -1
- package/fesm2022/aril-theme-layout.mjs +158 -21
- package/fesm2022/aril-theme-layout.mjs.map +1 -1
- package/fesm2022/aril.mjs +48 -4
- package/fesm2022/aril.mjs.map +1 -1
- package/package.json +212 -212
- package/scripts/mf-shared.js +47 -0
- package/theme/layout/service/breadcrumb-publisher.service.ts +18 -8
- package/theme/layout/service/interfaces/interfaces.d.ts +3 -17
- package/theme/layout/service/interfaces/interfaces.ts +6 -18
- package/theme/layout/service/selection-group.service.d.ts +8 -4
- package/theme/layout/service/selection-group.service.ts +161 -25
- package/fesm2022/aril-boot-mfe-aril-boot-mfe-KFO_X7yR.mjs.map +0 -1
|
@@ -1,36 +1,151 @@
|
|
|
1
|
-
import { Injectable
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
2
|
import { take } from 'rxjs';
|
|
3
|
+
import { bridge } from 'aril/boot/bridge';
|
|
3
4
|
import { API_CONFIGS } from 'aril/boot/config/api';
|
|
4
5
|
import * as i0 from "@angular/core";
|
|
5
6
|
import * as i1 from "@angular/common/http";
|
|
7
|
+
// Key başına maksimum ardışık fetch hatası: limit aşılınca o key oturum boyu yeniden denenmez.
|
|
8
|
+
// Sınırsız retry'da kalıcı hata veren bir grup (örn. silinmiş grup → 404), diğer grupların her
|
|
9
|
+
// başarılı yüklemesinde (map güncellemesi tüm enum computed'larını yeniden çalıştırır) yeniden
|
|
10
|
+
// POST edilirdi → istek/console fırtınası.
|
|
11
|
+
const MAX_FETCH_FAILURES = 3;
|
|
6
12
|
export class SelectionGroupService {
|
|
7
13
|
constructor(http) {
|
|
8
14
|
this.http = http;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
this.
|
|
12
|
-
this.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
// State cross-MFE paylaşımlı: bridge globalThis-singleton'ında yaşar (bkz. mfe-bridge.ts).
|
|
16
|
+
// Servis instance'ı MFE/tab başına çoğalsa da tüm okuma/yazma tek bridge state'ine gider.
|
|
17
|
+
this.selectionGroups = bridge.selectionGroups;
|
|
18
|
+
this.loading = bridge.selectionLoading;
|
|
19
|
+
this.loaded = bridge.selectionLoaded;
|
|
20
|
+
this.failures = bridge.selectionFailures;
|
|
21
|
+
// loadStates + invalidate yalnızca ilk instance'ta (cross-MFE bir kez): tek localStorage
|
|
22
|
+
// yüklemesi, tek `/versions` çağrısı. effect her instance'ta kurulur ama hepsi aynı paylaşılan
|
|
23
|
+
// state'i yazdığından ezme olmaz.
|
|
24
|
+
if (!bridge.selectionInitialized) {
|
|
25
|
+
bridge.selectionInitialized = true;
|
|
26
|
+
this.loadStatesFromLocalStorage();
|
|
27
|
+
this.invalidateStaleGroups();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// localStorage'a slim cache yazar. `effect` YERİNE bilinçli olarak doğrudan çağrılır: signal'i
|
|
31
|
+
// değiştiren her yer (fetchEnum, invalidateStaleGroups) persist'i açıkça tetikler. NOT: webpack MF
|
|
32
|
+
// config'iyle `@angular/core` artık singleton shared olduğundan effect-tabanlı persist de çalışırdı;
|
|
33
|
+
// yine de açık/öngörülebilir olması (effect içinde gizli signal-write + NG0600 riski olmaması) için
|
|
34
|
+
// doğrudan çağrı tercih edildi.
|
|
35
|
+
persistToLocalStorage() {
|
|
36
|
+
try {
|
|
37
|
+
const slim = this.slimForStorage(this.selectionGroups());
|
|
38
|
+
localStorage.setItem('selection-groups', btoa(encodeURI(JSON.stringify(slim))));
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// QuotaExceededError vb. → eski cache'i koru, yeni yazımı sessizce atla.
|
|
42
|
+
}
|
|
17
43
|
}
|
|
18
|
-
|
|
44
|
+
loadStatesFromLocalStorage() {
|
|
19
45
|
const selectionGroups = localStorage.getItem('selection-groups');
|
|
20
46
|
if (selectionGroups) {
|
|
21
47
|
try {
|
|
22
48
|
const decodedData = decodeURI(atob(selectionGroups));
|
|
23
|
-
|
|
49
|
+
// Dynamic gruplar zaten persist edilmiyor (slimForStorage onları atlar) → ekstra
|
|
50
|
+
// filtre gerekmez; localStorage içeriği yalnızca Fixed gruplardır.
|
|
51
|
+
const restored = JSON.parse(decodedData);
|
|
52
|
+
this.selectionGroups.set(restored);
|
|
53
|
+
// Restore edilen gruplar loaded sayılır: aksi halde koşulsuz fetchEnum çağıran
|
|
54
|
+
// consumer'lar guard'ı geçip her oturum yeniden çeker (cache faydası kaybolur).
|
|
55
|
+
// Stale'lik kontrolü invalidateStaleGroups'un işi. null entry'ler (legacy) loaded
|
|
56
|
+
// işaretlenmez — işaretlenirse o grup bir daha hiç yüklenemezdi.
|
|
57
|
+
Object.entries(restored).forEach(([key, group]) => {
|
|
58
|
+
if (group)
|
|
59
|
+
this.loaded.set(key, true);
|
|
60
|
+
});
|
|
24
61
|
}
|
|
25
62
|
catch (e) {
|
|
26
63
|
console.error(e);
|
|
27
64
|
}
|
|
28
65
|
}
|
|
29
66
|
}
|
|
67
|
+
// Dynamic grupları atlar + Fixed grupları yalnızca render (value/table/picker/export) ve invalidate
|
|
68
|
+
// için gerekli alanlara indirger. localStorage'da audit/id/açıklama gibi kullanılmayan alanları tutmaz.
|
|
69
|
+
slimForStorage(groups) {
|
|
70
|
+
const out = {};
|
|
71
|
+
for (const [key, group] of Object.entries(groups)) {
|
|
72
|
+
if (!group || group.loadStrategy === 'Dynamic')
|
|
73
|
+
continue;
|
|
74
|
+
out[key] = {
|
|
75
|
+
version: group.version,
|
|
76
|
+
selectionItems: (group.selectionItems ?? []).map((it) => ({
|
|
77
|
+
selectionKey: it.selectionKey,
|
|
78
|
+
selectionDisplay: it.selectionDisplay,
|
|
79
|
+
selectionMultiLanguageDisplays: it.selectionMultiLanguageDisplays,
|
|
80
|
+
showOrder: it.showOrder,
|
|
81
|
+
parentSelectionKey: it.parentSelectionKey
|
|
82
|
+
}))
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
// App init'te enum version'larını çekip localStorage'daki stale grupları temizler.
|
|
88
|
+
// Silinen grup, tüketici component'lerin `if (!selectionGroup) fetchEnum()` guard'ıyla yeniden yüklenir.
|
|
89
|
+
invalidateStaleGroups() {
|
|
90
|
+
// App-init snapshot: yalnızca localStorage'dan yüklenen gruplar kontrol edilir. Yanıt gelene
|
|
91
|
+
// kadar consumer'ların fetchEnum ile yüklediği taze gruplar taranmaz/silinmez (aksi halde
|
|
92
|
+
// taze grup silinir ve kalıcı per-component fetch guard'ları onu bir daha çekmeyebilir).
|
|
93
|
+
const keysToCheck = Object.keys(this.selectionGroups());
|
|
94
|
+
if (keysToCheck.length === 0)
|
|
95
|
+
return;
|
|
96
|
+
const hostApi = API_CONFIGS.api.replace(/\/[^\/]+\/v1$/, `/host/v1`);
|
|
97
|
+
this.http
|
|
98
|
+
.get(hostApi + '/selection-group/versions')
|
|
99
|
+
.pipe(take(1))
|
|
100
|
+
.subscribe({
|
|
101
|
+
next: (versions) => {
|
|
102
|
+
// Boş/bozuk yanıt güvenlik şeridi: aşağıdaki "listede olmayanı sil" kuralı
|
|
103
|
+
// boş listeyle tüm cache'i yanlışlıkla boşaltmasın.
|
|
104
|
+
if (!versions?.length)
|
|
105
|
+
return;
|
|
106
|
+
const latest = new Map(versions.map((v) => [v.groupName, v.version]));
|
|
107
|
+
let changed = false;
|
|
108
|
+
const next = { ...this.selectionGroups() };
|
|
109
|
+
keysToCheck.forEach((key) => {
|
|
110
|
+
const group = next[key];
|
|
111
|
+
if (!group)
|
|
112
|
+
return;
|
|
113
|
+
const separatorIndex = key.indexOf('~');
|
|
114
|
+
if (separatorIndex === -1)
|
|
115
|
+
return;
|
|
116
|
+
const serverVersion = latest.get(key.substring(0, separatorIndex));
|
|
117
|
+
// serverVersion == null: grup /versions listesinde yok → sunucudan silinmiş /
|
|
118
|
+
// yeniden adlandırılmış demektir (endpoint Fixed grupların tam listesini döner)
|
|
119
|
+
// → o da evict edilir; kalırsa kaldırılmış enum değerleri süresiz render edilir.
|
|
120
|
+
if (serverVersion == null || serverVersion !== group.version) {
|
|
121
|
+
delete next[key];
|
|
122
|
+
this.loaded.delete(key);
|
|
123
|
+
this.failures.delete(key);
|
|
124
|
+
// Uçuştaki fetch'in flag'i korunur: silinirse ikinci bir consumer guard'ı
|
|
125
|
+
// geçip duplicate /load atar ve export-overlay'in isLoading poll'ü grubu
|
|
126
|
+
// beklemeden erken geçer. Yanıt geldiğinde flag'i fetchEnum kendisi yönetir.
|
|
127
|
+
if (!this.loading.get(key)) {
|
|
128
|
+
this.loading.delete(key);
|
|
129
|
+
}
|
|
130
|
+
changed = true;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
if (changed) {
|
|
134
|
+
this.selectionGroups.set(next);
|
|
135
|
+
this.persistToLocalStorage();
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
error: () => {
|
|
139
|
+
// versions endpoint yok/erişilemez: sessizce mevcut cache ile devam.
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
30
143
|
fetchEnum(groupName, parentSelectionKey = 'ALL') {
|
|
31
144
|
const key = groupName + '~' + parentSelectionKey;
|
|
32
145
|
if (this.loaded.get(key) || this.loading.get(key))
|
|
33
146
|
return;
|
|
147
|
+
if ((this.failures.get(key) ?? 0) >= MAX_FETCH_FAILURES)
|
|
148
|
+
return;
|
|
34
149
|
const payload = {
|
|
35
150
|
groupName,
|
|
36
151
|
parentSelectionKey
|
|
@@ -41,17 +156,32 @@ export class SelectionGroupService {
|
|
|
41
156
|
this.http
|
|
42
157
|
.post(hostApi + '/selection-group/load', payload)
|
|
43
158
|
.pipe(take(1))
|
|
44
|
-
.subscribe(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
159
|
+
.subscribe({
|
|
160
|
+
next: (selectionGroup) => {
|
|
161
|
+
this.loading.set(key, false);
|
|
162
|
+
this.loaded.set(key, true);
|
|
163
|
+
this.failures.delete(key);
|
|
164
|
+
this.selectionGroups.update((groups) => ({
|
|
165
|
+
...groups,
|
|
166
|
+
[key]: selectionGroup
|
|
167
|
+
}));
|
|
168
|
+
this.persistToLocalStorage();
|
|
169
|
+
},
|
|
170
|
+
// HTTP hatasında loading'i sıfırla: aksi halde guard (loaded/loading) bu enum'u
|
|
171
|
+
// kilitler. loading/loaded bridge'de cross-MFE SHARED olduğundan, tek bir anlık hata
|
|
172
|
+
// bu enum'u TÜM remote'larda hard-reload'a kadar bir daha çekilemez yapardı. loading=false
|
|
173
|
+
// → sonraki fetchEnum (component init/retry) yeniden deneyebilir. loaded zaten false kalır.
|
|
174
|
+
// Deneme sayısı MAX_FETCH_FAILURES ile sınırlı: kalıcı hatada sonsuz retry önlenir.
|
|
175
|
+
error: () => {
|
|
176
|
+
this.loading.set(key, false);
|
|
177
|
+
this.failures.set(key, (this.failures.get(key) ?? 0) + 1);
|
|
178
|
+
}
|
|
51
179
|
});
|
|
52
180
|
}
|
|
53
|
-
|
|
54
|
-
|
|
181
|
+
// key formatı: `groupName~parentSelectionKey` (fetchEnum'daki composite key ile aynı).
|
|
182
|
+
// Direkt olarak groupName geçilirse Map'te eşleşme olmaz ve her zaman false döner.
|
|
183
|
+
isLoading(key) {
|
|
184
|
+
return this.loading.get(key) ?? false;
|
|
55
185
|
}
|
|
56
186
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: SelectionGroupService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
57
187
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: SelectionGroupService, providedIn: 'root' }); }
|
|
@@ -62,4 +192,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImpor
|
|
|
62
192
|
providedIn: 'root'
|
|
63
193
|
}]
|
|
64
194
|
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
65
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0aW9uLWdyb3VwLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hcmlsL3RoZW1lL2xheW91dC9zZXJ2aWNlL3NlbGVjdGlvbi1ncm91cC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUUzRCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRTVCLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQzs7O0FBT25ELE1BQU0sT0FBTyxxQkFBcUI7SUFNakMsWUFBb0IsSUFBZ0I7UUFBaEIsU0FBSSxHQUFKLElBQUksQ0FBWTtRQUxwQyxvQkFBZSxHQUFHLE1BQU0sQ0FBOEMsRUFBRSxDQUFDLENBQUM7UUFFbEUsWUFBTyxHQUFHLElBQUksR0FBRyxFQUFtQixDQUFDO1FBQ3JDLFdBQU0sR0FBRyxJQUFJLEdBQUcsRUFBbUIsQ0FBQztRQUczQyxJQUFJLENBQUMsMEJBQTBCLEVBQUUsQ0FBQztRQUVsQyxNQUFNLENBQUMsR0FBRyxFQUFFO1lBQ1gsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM1RSxZQUFZLENBQUMsT0FBTyxDQUFDLGtCQUFrQixFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQ3ZELENBQUMsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVPLEtBQUssQ0FBQywwQkFBMEI7UUFDdkMsTUFBTSxlQUFlLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBRWpFLElBQUksZUFBZSxFQUFFLENBQUM7WUFDckIsSUFBSSxDQUFDO2dCQUNKLE1BQU0sV0FBVyxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQztnQkFDckQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO1lBQ25ELENBQUM7WUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUNaLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDbEIsQ0FBQztRQUNGLENBQUM7SUFDRixDQUFDO0lBRUQsU0FBUyxDQUFDLFNBQWlCLEVBQUUscUJBQTZCLEtBQUs7UUFDOUQsTUFBTSxHQUFHLEdBQUcsU0FBUyxHQUFHLEdBQUcsR0FBRyxrQkFBa0IsQ0FBQztRQUVqRCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQztZQUFFLE9BQU87UUFFMUQsTUFBTSxPQUFPLEdBQXdCO1lBQ3BDLFNBQVM7WUFDVCxrQkFBa0I7U0FDbEIsQ0FBQztRQUVGLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUM1QixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFNUIsTUFBTSxPQUFPLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsZUFBZSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBRXJFLElBQUksQ0FBQyxJQUFJO2FBQ1AsSUFBSSxDQUFvQixPQUFPLEdBQUcsdUJBQXVCLEVBQUUsT0FBTyxDQUFDO2FBQ25FLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDYixTQUFTLENBQUMsQ0FBQyxjQUFjLEVBQUUsRUFBRTtZQUM3QixJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDN0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBRTNCLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUN4QyxHQUFHLE1BQU07Z0JBQ1QsQ0FBQyxHQUFHLENBQUMsRUFBRSxjQUFjO2FBQ3JCLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsU0FBUyxDQUFDLFNBQWlCO1FBQzFCLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLElBQUksS0FBSyxDQUFDO0lBQzdDLENBQUM7OEdBM0RXLHFCQUFxQjtrSEFBckIscUJBQXFCLGNBRnJCLE1BQU07OzJGQUVOLHFCQUFxQjtrQkFIakMsVUFBVTttQkFBQztvQkFDWCxVQUFVLEVBQUUsTUFBTTtpQkFDbEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBIdHRwQ2xpZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xyXG5pbXBvcnQgeyBJbmplY3RhYmxlLCBlZmZlY3QsIHNpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5cclxuaW1wb3J0IHsgdGFrZSB9IGZyb20gJ3J4anMnO1xyXG5cclxuaW1wb3J0IHsgQVBJX0NPTkZJR1MgfSBmcm9tICdhcmlsL2Jvb3QvY29uZmlnL2FwaSc7XHJcblxyXG5pbXBvcnQgeyBTZWxlY3Rpb25Hcm91cERUTywgU2VsZWN0aW9uUmVxdWVzdERUTyB9IGZyb20gJy4vaW50ZXJmYWNlcy9pbnRlcmZhY2VzJztcclxuXHJcbkBJbmplY3RhYmxlKHtcclxuXHRwcm92aWRlZEluOiAncm9vdCdcclxufSlcclxuZXhwb3J0IGNsYXNzIFNlbGVjdGlvbkdyb3VwU2VydmljZSB7XHJcblx0c2VsZWN0aW9uR3JvdXBzID0gc2lnbmFsPHsgW2tleTogc3RyaW5nXTogU2VsZWN0aW9uR3JvdXBEVE8gfCBudWxsIH0+KHt9KTtcclxuXHJcblx0cHJpdmF0ZSBsb2FkaW5nID0gbmV3IE1hcDxzdHJpbmcsIGJvb2xlYW4+KCk7XHJcblx0cHJpdmF0ZSBsb2FkZWQgPSBuZXcgTWFwPHN0cmluZywgYm9vbGVhbj4oKTtcclxuXHJcblx0Y29uc3RydWN0b3IocHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50KSB7XHJcblx0XHR0aGlzLmxvYWRTdGF0ZXNGcm9tTG9jYWxTdG9yYWdlKCk7XHJcblxyXG5cdFx0ZWZmZWN0KCgpID0+IHtcclxuXHRcdFx0Y29uc3QgZW5jb2RlZERhdGEgPSBidG9hKGVuY29kZVVSSShKU09OLnN0cmluZ2lmeSh0aGlzLnNlbGVjdGlvbkdyb3VwcygpKSkpO1xyXG5cdFx0XHRsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgnc2VsZWN0aW9uLWdyb3VwcycsIGVuY29kZWREYXRhKTtcclxuXHRcdH0pO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBhc3luYyBsb2FkU3RhdGVzRnJvbUxvY2FsU3RvcmFnZSgpIHtcclxuXHRcdGNvbnN0IHNlbGVjdGlvbkdyb3VwcyA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdzZWxlY3Rpb24tZ3JvdXBzJyk7XHJcblxyXG5cdFx0aWYgKHNlbGVjdGlvbkdyb3Vwcykge1xyXG5cdFx0XHR0cnkge1xyXG5cdFx0XHRcdGNvbnN0IGRlY29kZWREYXRhID0gZGVjb2RlVVJJKGF0b2Ioc2VsZWN0aW9uR3JvdXBzKSk7XHJcblx0XHRcdFx0dGhpcy5zZWxlY3Rpb25Hcm91cHMuc2V0KEpTT04ucGFyc2UoZGVjb2RlZERhdGEpKTtcclxuXHRcdFx0fSBjYXRjaCAoZSkge1xyXG5cdFx0XHRcdGNvbnNvbGUuZXJyb3IoZSk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdGZldGNoRW51bShncm91cE5hbWU6IHN0cmluZywgcGFyZW50U2VsZWN0aW9uS2V5OiBzdHJpbmcgPSAnQUxMJykge1xyXG5cdFx0Y29uc3Qga2V5ID0gZ3JvdXBOYW1lICsgJ34nICsgcGFyZW50U2VsZWN0aW9uS2V5O1xyXG5cclxuXHRcdGlmICh0aGlzLmxvYWRlZC5nZXQoa2V5KSB8fCB0aGlzLmxvYWRpbmcuZ2V0KGtleSkpIHJldHVybjtcclxuXHJcblx0XHRjb25zdCBwYXlsb2FkOiBTZWxlY3Rpb25SZXF1ZXN0RFRPID0ge1xyXG5cdFx0XHRncm91cE5hbWUsXHJcblx0XHRcdHBhcmVudFNlbGVjdGlvbktleVxyXG5cdFx0fTtcclxuXHJcblx0XHR0aGlzLmxvYWRpbmcuc2V0KGtleSwgdHJ1ZSk7XHJcblx0XHR0aGlzLmxvYWRlZC5zZXQoa2V5LCBmYWxzZSk7XHJcblxyXG5cdFx0Y29uc3QgaG9zdEFwaSA9IEFQSV9DT05GSUdTLmFwaS5yZXBsYWNlKC9cXC9bXlxcL10rXFwvdjEkLywgYC9ob3N0L3YxYCk7XHJcblxyXG5cdFx0dGhpcy5odHRwXHJcblx0XHRcdC5wb3N0PFNlbGVjdGlvbkdyb3VwRFRPPihob3N0QXBpICsgJy9zZWxlY3Rpb24tZ3JvdXAvbG9hZCcsIHBheWxvYWQpXHJcblx0XHRcdC5waXBlKHRha2UoMSkpXHJcblx0XHRcdC5zdWJzY3JpYmUoKHNlbGVjdGlvbkdyb3VwKSA9PiB7XHJcblx0XHRcdFx0dGhpcy5sb2FkaW5nLnNldChrZXksIGZhbHNlKTtcclxuXHRcdFx0XHR0aGlzLmxvYWRlZC5zZXQoa2V5LCB0cnVlKTtcclxuXHJcblx0XHRcdFx0dGhpcy5zZWxlY3Rpb25Hcm91cHMudXBkYXRlKChncm91cHMpID0+ICh7XHJcblx0XHRcdFx0XHQuLi5ncm91cHMsXHJcblx0XHRcdFx0XHRba2V5XTogc2VsZWN0aW9uR3JvdXBcclxuXHRcdFx0XHR9KSk7XHJcblx0XHRcdH0pO1xyXG5cdH1cclxuXHJcblx0aXNMb2FkaW5nKGdyb3VwTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XHJcblx0XHRyZXR1cm4gdGhpcy5sb2FkaW5nLmdldChncm91cE5hbWUpID8/IGZhbHNlO1xyXG5cdH1cclxufVxyXG4iXX0=
|
|
195
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0aW9uLWdyb3VwLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hcmlsL3RoZW1lL2xheW91dC9zZXJ2aWNlL3NlbGVjdGlvbi1ncm91cC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFM0MsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUU1QixPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDMUMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDOzs7QUFJbkQsK0ZBQStGO0FBQy9GLCtGQUErRjtBQUMvRiwrRkFBK0Y7QUFDL0YsMkNBQTJDO0FBQzNDLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxDQUFDO0FBSzdCLE1BQU0sT0FBTyxxQkFBcUI7SUFTakMsWUFBNkIsSUFBZ0I7UUFBaEIsU0FBSSxHQUFKLElBQUksQ0FBWTtRQVI3QywyRkFBMkY7UUFDM0YsMEZBQTBGO1FBQzFGLG9CQUFlLEdBQUcsTUFBTSxDQUFDLGVBQWUsQ0FBQztRQUV4QixZQUFPLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixDQUFDO1FBQ2xDLFdBQU0sR0FBRyxNQUFNLENBQUMsZUFBZSxDQUFDO1FBQ2hDLGFBQVEsR0FBRyxNQUFNLENBQUMsaUJBQWlCLENBQUM7UUFHcEQseUZBQXlGO1FBQ3pGLCtGQUErRjtRQUMvRixrQ0FBa0M7UUFDbEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1lBQ2xDLE1BQU0sQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLENBQUM7WUFDbkMsSUFBSSxDQUFDLDBCQUEwQixFQUFFLENBQUM7WUFDbEMsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDOUIsQ0FBQztJQUNGLENBQUM7SUFFRCwrRkFBK0Y7SUFDL0Ys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Q0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDN0IsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDM0QsQ0FBQztTQUNELENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCx1RkFBdUY7SUFDdkYsbUZBQW1GO0lBQ25GLFNBQVMsQ0FBQyxHQUFXO1FBQ3BCLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksS0FBSyxDQUFDO0lBQ3ZDLENBQUM7OEdBNUxXLHFCQUFxQjtrSEFBckIscUJBQXFCLGNBRnJCLE1BQU07OzJGQUVOLHFCQUFxQjtrQkFIakMsVUFBVTttQkFBQztvQkFDWCxVQUFVLEVBQUUsTUFBTTtpQkFDbEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBIdHRwQ2xpZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xyXG5pbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcblxyXG5pbXBvcnQgeyB0YWtlIH0gZnJvbSAncnhqcyc7XHJcblxyXG5pbXBvcnQgeyBicmlkZ2UgfSBmcm9tICdhcmlsL2Jvb3QvYnJpZGdlJztcclxuaW1wb3J0IHsgQVBJX0NPTkZJR1MgfSBmcm9tICdhcmlsL2Jvb3QvY29uZmlnL2FwaSc7XHJcblxyXG5pbXBvcnQgeyBTZWxlY3Rpb25Hcm91cERUTywgU2VsZWN0aW9uR3JvdXBWZXJzaW9uRFRPLCBTZWxlY3Rpb25SZXF1ZXN0RFRPIH0gZnJvbSAnLi9pbnRlcmZhY2VzL2ludGVyZmFjZXMnO1xyXG5cclxuLy8gS2V5IGJhxZ/EsW5hIG1ha3NpbXVtIGFyZMSxxZ/EsWsgZmV0Y2ggaGF0YXPEsTogbGltaXQgYcWfxLFsxLFuY2EgbyBrZXkgb3R1cnVtIGJveXUgeWVuaWRlbiBkZW5lbm1lei5cclxuLy8gU8SxbsSxcnPEsXogcmV0cnknZGEga2FsxLFjxLEgaGF0YSB2ZXJlbiBiaXIgZ3J1cCAow7Zybi4gc2lsaW5tacWfIGdydXAg4oaSIDQwNCksIGRpxJ9lciBncnVwbGFyxLFuIGhlclxyXG4vLyBiYcWfYXLEsWzEsSB5w7xrbGVtZXNpbmRlIChtYXAgZ8O8bmNlbGxlbWVzaSB0w7xtIGVudW0gY29tcHV0ZWQnbGFyxLFuxLEgeWVuaWRlbiDDp2FsxLHFn3TEsXLEsXIpIHllbmlkZW5cclxuLy8gUE9TVCBlZGlsaXJkaSDihpIgaXN0ZWsvY29uc29sZSBmxLFydMSxbmFzxLEuXHJcbmNvbnN0IE1BWF9GRVRDSF9GQUlMVVJFUyA9IDM7XHJcblxyXG5ASW5qZWN0YWJsZSh7XHJcblx0cHJvdmlkZWRJbjogJ3Jvb3QnXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBTZWxlY3Rpb25Hcm91cFNlcnZpY2Uge1xyXG5cdC8vIFN0YXRlIGNyb3NzLU1GRSBwYXlsYcWfxLFtbMSxOiBicmlkZ2UgZ2xvYmFsVGhpcy1zaW5nbGV0b24nxLFuZGEgeWHFn2FyIChia3ouIG1mZS1icmlkZ2UudHMpLlxyXG5cdC8vIFNlcnZpcyBpbnN0YW5jZSfEsSBNRkUvdGFiIGJhxZ/EsW5hIMOnb8SfYWxzYSBkYSB0w7xtIG9rdW1hL3lhem1hIHRlayBicmlkZ2Ugc3RhdGUnaW5lIGdpZGVyLlxyXG5cdHNlbGVjdGlvbkdyb3VwcyA9IGJyaWRnZS5zZWxlY3Rpb25Hcm91cHM7XHJcblxyXG5cdHByaXZhdGUgcmVhZG9ubHkgbG9hZGluZyA9IGJyaWRnZS5zZWxlY3Rpb25Mb2FkaW5nO1xyXG5cdHByaXZhdGUgcmVhZG9ubHkgbG9hZGVkID0gYnJpZGdlLnNlbGVjdGlvbkxvYWRlZDtcclxuXHRwcml2YXRlIHJlYWRvbmx5IGZhaWx1cmVzID0gYnJpZGdlLnNlbGVjdGlvbkZhaWx1cmVzO1xyXG5cclxuXHRjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGh0dHA6IEh0dHBDbGllbnQpIHtcclxuXHRcdC8vIGxvYWRTdGF0ZXMgKyBpbnZhbGlkYXRlIHlhbG7EsXpjYSBpbGsgaW5zdGFuY2UndGEgKGNyb3NzLU1GRSBiaXIga2V6KTogdGVrIGxvY2FsU3RvcmFnZVxyXG5cdFx0Ly8gecO8a2xlbWVzaSwgdGVrIGAvdmVyc2lvbnNgIMOnYcSfcsSxc8SxLiBlZmZlY3QgaGVyIGluc3RhbmNlJ3RhIGt1cnVsdXIgYW1hIGhlcHNpIGF5bsSxIHBheWxhxZ/EsWxhblxyXG5cdFx0Ly8gc3RhdGUnaSB5YXpkxLHEn8SxbmRhbiBlem1lIG9sbWF6LlxyXG5cdFx0aWYgKCFicmlkZ2Uuc2VsZWN0aW9uSW5pdGlhbGl6ZWQpIHtcclxuXHRcdFx0YnJpZGdlLnNlbGVjdGlvbkluaXRpYWxpemVkID0gdHJ1ZTtcclxuXHRcdFx0dGhpcy5sb2FkU3RhdGVzRnJvbUxvY2FsU3RvcmFnZSgpO1xyXG5cdFx0XHR0aGlzLmludmFsaWRhdGVTdGFsZUdyb3VwcygpO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0Ly8gbG9jYWxTdG9yYWdlJ2Egc2xpbSBjYWNoZSB5YXphci4gYGVmZmVjdGAgWUVSxLBORSBiaWxpbsOnbGkgb2xhcmFrIGRvxJ9ydWRhbiDDp2HEn3LEsWzEsXI6IHNpZ25hbCdpXHJcblx0Ly8gZGXEn2nFn3RpcmVuIGhlciB5ZXIgKGZldGNoRW51bSwgaW52YWxpZGF0ZVN0YWxlR3JvdXBzKSBwZXJzaXN0J2kgYcOnxLFrw6dhIHRldGlrbGVyLiBOT1Q6IHdlYnBhY2sgTUZcclxuXHQvLyBjb25maWcnaXlsZSBgQGFuZ3VsYXIvY29yZWAgYXJ0xLFrIHNpbmdsZXRvbiBzaGFyZWQgb2xkdcSfdW5kYW4gZWZmZWN0LXRhYmFubMSxIHBlcnNpc3QgZGUgw6dhbMSxxZ/EsXJkxLE7XHJcblx0Ly8geWluZSBkZSBhw6fEsWsvw7ZuZ8O2csO8bGViaWxpciBvbG1hc8SxIChlZmZlY3QgacOnaW5kZSBnaXpsaSBzaWduYWwtd3JpdGUgKyBORzA2MDAgcmlza2kgb2xtYW1hc8SxKSBpw6dpblxyXG5cdC8vIGRvxJ9ydWRhbiDDp2HEn3LEsSB0ZXJjaWggZWRpbGRpLlxyXG5cdHByaXZhdGUgcGVyc2lzdFRvTG9jYWxTdG9yYWdlKCkge1xyXG5cdFx0dHJ5IHtcclxuXHRcdFx0Y29uc3Qgc2xpbSA9IHRoaXMuc2xpbUZvclN0b3JhZ2UodGhpcy5zZWxlY3Rpb25Hcm91cHMoKSk7XHJcblx0XHRcdGxvY2FsU3RvcmFnZS5zZXRJdGVtKCdzZWxlY3Rpb24tZ3JvdXBzJywgYnRvYShlbmNvZGVVUkkoSlNPTi5zdHJpbmdpZnkoc2xpbSkpKSk7XHJcblx0XHR9IGNhdGNoIHtcclxuXHRcdFx0Ly8gUXVvdGFFeGNlZWRlZEVycm9yIHZiLiDihpIgZXNraSBjYWNoZSdpIGtvcnUsIHllbmkgeWF6xLFtxLEgc2Vzc2l6Y2UgYXRsYS5cclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHByaXZhdGUgbG9hZFN0YXRlc0Zyb21Mb2NhbFN0b3JhZ2UoKSB7XHJcblx0XHRjb25zdCBzZWxlY3Rpb25Hcm91cHMgPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnc2VsZWN0aW9uLWdyb3VwcycpO1xyXG5cclxuXHRcdGlmIChzZWxlY3Rpb25Hcm91cHMpIHtcclxuXHRcdFx0dHJ5IHtcclxuXHRcdFx0XHRjb25zdCBkZWNvZGVkRGF0YSA9IGRlY29kZVVSSShhdG9iKHNlbGVjdGlvbkdyb3VwcykpO1xyXG5cdFx0XHRcdC8vIER5bmFtaWMgZ3J1cGxhciB6YXRlbiBwZXJzaXN0IGVkaWxtaXlvciAoc2xpbUZvclN0b3JhZ2Ugb25sYXLEsSBhdGxhcikg4oaSIGVrc3RyYVxyXG5cdFx0XHRcdC8vIGZpbHRyZSBnZXJla21lejsgbG9jYWxTdG9yYWdlIGnDp2VyacSfaSB5YWxuxLF6Y2EgRml4ZWQgZ3J1cGxhcmTEsXIuXHJcblx0XHRcdFx0Y29uc3QgcmVzdG9yZWQ6IHsgW2tleTogc3RyaW5nXTogU2VsZWN0aW9uR3JvdXBEVE8gfCBudWxsIH0gPSBKU09OLnBhcnNlKGRlY29kZWREYXRhKTtcclxuXHRcdFx0XHR0aGlzLnNlbGVjdGlvbkdyb3Vwcy5zZXQocmVzdG9yZWQpO1xyXG5cclxuXHRcdFx0XHQvLyBSZXN0b3JlIGVkaWxlbiBncnVwbGFyIGxvYWRlZCBzYXnEsWzEsXI6IGFrc2kgaGFsZGUga2/Fn3Vsc3V6IGZldGNoRW51bSDDp2HEn8SxcmFuXHJcblx0XHRcdFx0Ly8gY29uc3VtZXInbGFyIGd1YXJkJ8SxIGdlw6dpcCBoZXIgb3R1cnVtIHllbmlkZW4gw6dla2VyIChjYWNoZSBmYXlkYXPEsSBrYXlib2x1cikuXHJcblx0XHRcdFx0Ly8gU3RhbGUnbGlrIGtvbnRyb2zDvCBpbnZhbGlkYXRlU3RhbGVHcm91cHMndW4gacWfaS4gbnVsbCBlbnRyeSdsZXIgKGxlZ2FjeSkgbG9hZGVkXHJcblx0XHRcdFx0Ly8gacWfYXJldGxlbm1leiDigJQgacWfYXJldGxlbmlyc2UgbyBncnVwIGJpciBkYWhhIGhpw6cgecO8a2xlbmVtZXpkaS5cclxuXHRcdFx0XHRPYmplY3QuZW50cmllcyhyZXN0b3JlZCkuZm9yRWFjaCgoW2tleSwgZ3JvdXBdKSA9PiB7XHJcblx0XHRcdFx0XHRpZiAoZ3JvdXApIHRoaXMubG9hZGVkLnNldChrZXksIHRydWUpO1xyXG5cdFx0XHRcdH0pO1xyXG5cdFx0XHR9IGNhdGNoIChlKSB7XHJcblx0XHRcdFx0Y29uc29sZS5lcnJvcihlKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0Ly8gRHluYW1pYyBncnVwbGFyxLEgYXRsYXIgKyBGaXhlZCBncnVwbGFyxLEgeWFsbsSxemNhIHJlbmRlciAodmFsdWUvdGFibGUvcGlja2VyL2V4cG9ydCkgdmUgaW52YWxpZGF0ZVxyXG5cdC8vIGnDp2luIGdlcmVrbGkgYWxhbmxhcmEgaW5kaXJnZXIuIGxvY2FsU3RvcmFnZSdkYSBhdWRpdC9pZC9hw6fEsWtsYW1hIGdpYmkga3VsbGFuxLFsbWF5YW4gYWxhbmxhcsSxIHR1dG1hei5cclxuXHRwcml2YXRlIHNsaW1Gb3JTdG9yYWdlKGdyb3VwczogeyBba2V5OiBzdHJpbmddOiBTZWxlY3Rpb25Hcm91cERUTyB8IG51bGwgfSk6IHsgW2tleTogc3RyaW5nXTogdW5rbm93biB9IHtcclxuXHRcdGNvbnN0IG91dDogeyBba2V5OiBzdHJpbmddOiB1bmtub3duIH0gPSB7fTtcclxuXHRcdGZvciAoY29uc3QgW2tleSwgZ3JvdXBdIG9mIE9iamVjdC5lbnRyaWVzKGdyb3VwcykpIHtcclxuXHRcdFx0aWYgKCFncm91cCB8fCBncm91cC5sb2FkU3RyYXRlZ3kgPT09ICdEeW5hbWljJykgY29udGludWU7XHJcblx0XHRcdG91dFtrZXldID0ge1xyXG5cdFx0XHRcdHZlcnNpb246IGdyb3VwLnZlcnNpb24sXHJcblx0XHRcdFx0c2VsZWN0aW9uSXRlbXM6IChncm91cC5zZWxlY3Rpb25JdGVtcyA/PyBbXSkubWFwKChpdCkgPT4gKHtcclxuXHRcdFx0XHRcdHNlbGVjdGlvbktleTogaXQuc2VsZWN0aW9uS2V5LFxyXG5cdFx0XHRcdFx0c2VsZWN0aW9uRGlzcGxheTogaXQuc2VsZWN0aW9uRGlzcGxheSxcclxuXHRcdFx0XHRcdHNlbGVjdGlvbk11bHRpTGFuZ3VhZ2VEaXNwbGF5czogaXQuc2VsZWN0aW9uTXVsdGlMYW5ndWFnZURpc3BsYXlzLFxyXG5cdFx0XHRcdFx0c2hvd09yZGVyOiBpdC5zaG93T3JkZXIsXHJcblx0XHRcdFx0XHRwYXJlbnRTZWxlY3Rpb25LZXk6IGl0LnBhcmVudFNlbGVjdGlvbktleVxyXG5cdFx0XHRcdH0pKVxyXG5cdFx0XHR9O1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIG91dDtcclxuXHR9XHJcblxyXG5cdC8vIEFwcCBpbml0J3RlIGVudW0gdmVyc2lvbidsYXLEsW7EsSDDp2VraXAgbG9jYWxTdG9yYWdlJ2Rha2kgc3RhbGUgZ3J1cGxhcsSxIHRlbWl6bGVyLlxyXG5cdC8vIFNpbGluZW4gZ3J1cCwgdMO8a2V0aWNpIGNvbXBvbmVudCdsZXJpbiBgaWYgKCFzZWxlY3Rpb25Hcm91cCkgZmV0Y2hFbnVtKClgIGd1YXJkJ8SxeWxhIHllbmlkZW4gecO8a2xlbmlyLlxyXG5cdHByaXZhdGUgaW52YWxpZGF0ZVN0YWxlR3JvdXBzKCkge1xyXG5cdFx0Ly8gQXBwLWluaXQgc25hcHNob3Q6IHlhbG7EsXpjYSBsb2NhbFN0b3JhZ2UnZGFuIHnDvGtsZW5lbiBncnVwbGFyIGtvbnRyb2wgZWRpbGlyLiBZYW7EsXQgZ2VsZW5lXHJcblx0XHQvLyBrYWRhciBjb25zdW1lcidsYXLEsW4gZmV0Y2hFbnVtIGlsZSB5w7xrbGVkacSfaSB0YXplIGdydXBsYXIgdGFyYW5tYXovc2lsaW5tZXogKGFrc2kgaGFsZGVcclxuXHRcdC8vIHRhemUgZ3J1cCBzaWxpbmlyIHZlIGthbMSxY8SxIHBlci1jb21wb25lbnQgZmV0Y2ggZ3VhcmQnbGFyxLEgb251IGJpciBkYWhhIMOnZWttZXllYmlsaXIpLlxyXG5cdFx0Y29uc3Qga2V5c1RvQ2hlY2sgPSBPYmplY3Qua2V5cyh0aGlzLnNlbGVjdGlvbkdyb3VwcygpKTtcclxuXHRcdGlmIChrZXlzVG9DaGVjay5sZW5ndGggPT09IDApIHJldHVybjtcclxuXHJcblx0XHRjb25zdCBob3N0QXBpID0gQVBJX0NPTkZJR1MuYXBpLnJlcGxhY2UoL1xcL1teXFwvXStcXC92MSQvLCBgL2hvc3QvdjFgKTtcclxuXHJcblx0XHR0aGlzLmh0dHBcclxuXHRcdFx0LmdldDxTZWxlY3Rpb25Hcm91cFZlcnNpb25EVE9bXT4oaG9zdEFwaSArICcvc2VsZWN0aW9uLWdyb3VwL3ZlcnNpb25zJylcclxuXHRcdFx0LnBpcGUodGFrZSgxKSlcclxuXHRcdFx0LnN1YnNjcmliZSh7XHJcblx0XHRcdFx0bmV4dDogKHZlcnNpb25zKSA9PiB7XHJcblx0XHRcdFx0XHQvLyBCb8WfL2JvenVrIHlhbsSxdCBnw7x2ZW5saWsgxZ9lcmlkaTogYcWfYcSfxLFkYWtpIFwibGlzdGVkZSBvbG1heWFuxLEgc2lsXCIga3VyYWzEsVxyXG5cdFx0XHRcdFx0Ly8gYm/FnyBsaXN0ZXlsZSB0w7xtIGNhY2hlJ2kgeWFubMSxxZ9sxLFrbGEgYm/Fn2FsdG1hc8Sxbi5cclxuXHRcdFx0XHRcdGlmICghdmVyc2lvbnM/Lmxlbmd0aCkgcmV0dXJuO1xyXG5cclxuXHRcdFx0XHRcdGNvbnN0IGxhdGVzdCA9IG5ldyBNYXAodmVyc2lvbnMubWFwKCh2KSA9PiBbdi5ncm91cE5hbWUsIHYudmVyc2lvbl0gYXMgW3N0cmluZywgbnVtYmVyXSkpO1xyXG5cclxuXHRcdFx0XHRcdGxldCBjaGFuZ2VkID0gZmFsc2U7XHJcblx0XHRcdFx0XHRjb25zdCBuZXh0ID0geyAuLi50aGlzLnNlbGVjdGlvbkdyb3VwcygpIH07XHJcblxyXG5cdFx0XHRcdFx0a2V5c1RvQ2hlY2suZm9yRWFjaCgoa2V5KSA9PiB7XHJcblx0XHRcdFx0XHRcdGNvbnN0IGdyb3VwID0gbmV4dFtrZXldO1xyXG5cdFx0XHRcdFx0XHRpZiAoIWdyb3VwKSByZXR1cm47XHJcblxyXG5cdFx0XHRcdFx0XHRjb25zdCBzZXBhcmF0b3JJbmRleCA9IGtleS5pbmRleE9mKCd+Jyk7XHJcblx0XHRcdFx0XHRcdGlmIChzZXBhcmF0b3JJbmRleCA9PT0gLTEpIHJldHVybjtcclxuXHJcblx0XHRcdFx0XHRcdGNvbnN0IHNlcnZlclZlcnNpb24gPSBsYXRlc3QuZ2V0KGtleS5zdWJzdHJpbmcoMCwgc2VwYXJhdG9ySW5kZXgpKTtcclxuXHJcblx0XHRcdFx0XHRcdC8vIHNlcnZlclZlcnNpb24gPT0gbnVsbDogZ3J1cCAvdmVyc2lvbnMgbGlzdGVzaW5kZSB5b2sg4oaSIHN1bnVjdWRhbiBzaWxpbm1pxZ8gL1xyXG5cdFx0XHRcdFx0XHQvLyB5ZW5pZGVuIGFkbGFuZMSxcsSxbG3EscWfIGRlbWVrdGlyIChlbmRwb2ludCBGaXhlZCBncnVwbGFyxLFuIHRhbSBsaXN0ZXNpbmkgZMO2bmVyKVxyXG5cdFx0XHRcdFx0XHQvLyDihpIgbyBkYSBldmljdCBlZGlsaXI7IGthbMSxcnNhIGthbGTEsXLEsWxtxLHFnyBlbnVtIGRlxJ9lcmxlcmkgc8O8cmVzaXogcmVuZGVyIGVkaWxpci5cclxuXHRcdFx0XHRcdFx0aWYgKHNlcnZlclZlcnNpb24gPT0gbnVsbCB8fCBzZXJ2ZXJWZXJzaW9uICE9PSBncm91cC52ZXJzaW9uKSB7XHJcblx0XHRcdFx0XHRcdFx0ZGVsZXRlIG5leHRba2V5XTtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLmxvYWRlZC5kZWxldGUoa2V5KTtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLmZhaWx1cmVzLmRlbGV0ZShrZXkpO1xyXG5cdFx0XHRcdFx0XHRcdC8vIFXDp3XFn3Rha2kgZmV0Y2gnaW4gZmxhZydpIGtvcnVudXI6IHNpbGluaXJzZSBpa2luY2kgYmlyIGNvbnN1bWVyIGd1YXJkJ8SxXHJcblx0XHRcdFx0XHRcdFx0Ly8gZ2XDp2lwIGR1cGxpY2F0ZSAvbG9hZCBhdGFyIHZlIGV4cG9ydC1vdmVybGF5J2luIGlzTG9hZGluZyBwb2xsJ8O8IGdydWJ1XHJcblx0XHRcdFx0XHRcdFx0Ly8gYmVrbGVtZWRlbiBlcmtlbiBnZcOnZXIuIFlhbsSxdCBnZWxkacSfaW5kZSBmbGFnJ2kgZmV0Y2hFbnVtIGtlbmRpc2kgecO2bmV0aXIuXHJcblx0XHRcdFx0XHRcdFx0aWYgKCF0aGlzLmxvYWRpbmcuZ2V0KGtleSkpIHtcclxuXHRcdFx0XHRcdFx0XHRcdHRoaXMubG9hZGluZy5kZWxldGUoa2V5KTtcclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0Y2hhbmdlZCA9IHRydWU7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH0pO1xyXG5cclxuXHRcdFx0XHRcdGlmIChjaGFuZ2VkKSB7XHJcblx0XHRcdFx0XHRcdHRoaXMuc2VsZWN0aW9uR3JvdXBzLnNldChuZXh0KTtcclxuXHRcdFx0XHRcdFx0dGhpcy5wZXJzaXN0VG9Mb2NhbFN0b3JhZ2UoKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9LFxyXG5cdFx0XHRcdGVycm9yOiAoKSA9PiB7XHJcblx0XHRcdFx0XHQvLyB2ZXJzaW9ucyBlbmRwb2ludCB5b2svZXJpxZ9pbGVtZXo6IHNlc3NpemNlIG1ldmN1dCBjYWNoZSBpbGUgZGV2YW0uXHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9KTtcclxuXHR9XHJcblxyXG5cdGZldGNoRW51bShncm91cE5hbWU6IHN0cmluZywgcGFyZW50U2VsZWN0aW9uS2V5OiBzdHJpbmcgPSAnQUxMJykge1xyXG5cdFx0Y29uc3Qga2V5ID0gZ3JvdXBOYW1lICsgJ34nICsgcGFyZW50U2VsZWN0aW9uS2V5O1xyXG5cclxuXHRcdGlmICh0aGlzLmxvYWRlZC5nZXQoa2V5KSB8fCB0aGlzLmxvYWRpbmcuZ2V0KGtleSkpIHJldHVybjtcclxuXHRcdGlmICgodGhpcy5mYWlsdXJlcy5nZXQoa2V5KSA/PyAwKSA+PSBNQVhfRkVUQ0hfRkFJTFVSRVMpIHJldHVybjtcclxuXHJcblx0XHRjb25zdCBwYXlsb2FkOiBTZWxlY3Rpb25SZXF1ZXN0RFRPID0ge1xyXG5cdFx0XHRncm91cE5hbWUsXHJcblx0XHRcdHBhcmVudFNlbGVjdGlvbktleVxyXG5cdFx0fTtcclxuXHJcblx0XHR0aGlzLmxvYWRpbmcuc2V0KGtleSwgdHJ1ZSk7XHJcblx0XHR0aGlzLmxvYWRlZC5zZXQoa2V5LCBmYWxzZSk7XHJcblxyXG5cdFx0Y29uc3QgaG9zdEFwaSA9IEFQSV9DT05GSUdTLmFwaS5yZXBsYWNlKC9cXC9bXlxcL10rXFwvdjEkLywgYC9ob3N0L3YxYCk7XHJcblxyXG5cdFx0dGhpcy5odHRwXHJcblx0XHRcdC5wb3N0PFNlbGVjdGlvbkdyb3VwRFRPPihob3N0QXBpICsgJy9zZWxlY3Rpb24tZ3JvdXAvbG9hZCcsIHBheWxvYWQpXHJcblx0XHRcdC5waXBlKHRha2UoMSkpXHJcblx0XHRcdC5zdWJzY3JpYmUoe1xyXG5cdFx0XHRcdG5leHQ6IChzZWxlY3Rpb25Hcm91cCkgPT4ge1xyXG5cdFx0XHRcdFx0dGhpcy5sb2FkaW5nLnNldChrZXksIGZhbHNlKTtcclxuXHRcdFx0XHRcdHRoaXMubG9hZGVkLnNldChrZXksIHRydWUpO1xyXG5cdFx0XHRcdFx0dGhpcy5mYWlsdXJlcy5kZWxldGUoa2V5KTtcclxuXHJcblx0XHRcdFx0XHR0aGlzLnNlbGVjdGlvbkdyb3Vwcy51cGRhdGUoKGdyb3VwcykgPT4gKHtcclxuXHRcdFx0XHRcdFx0Li4uZ3JvdXBzLFxyXG5cdFx0XHRcdFx0XHRba2V5XTogc2VsZWN0aW9uR3JvdXBcclxuXHRcdFx0XHRcdH0pKTtcclxuXHJcblx0XHRcdFx0XHR0aGlzLnBlcnNpc3RUb0xvY2FsU3RvcmFnZSgpO1xyXG5cdFx0XHRcdH0sXHJcblx0XHRcdFx0Ly8gSFRUUCBoYXRhc8SxbmRhIGxvYWRpbmcnaSBzxLFmxLFybGE6IGFrc2kgaGFsZGUgZ3VhcmQgKGxvYWRlZC9sb2FkaW5nKSBidSBlbnVtJ3VcclxuXHRcdFx0XHQvLyBraWxpdGxlci4gbG9hZGluZy9sb2FkZWQgYnJpZGdlJ2RlIGNyb3NzLU1GRSBTSEFSRUQgb2xkdcSfdW5kYW4sIHRlayBiaXIgYW5sxLFrIGhhdGFcclxuXHRcdFx0XHQvLyBidSBlbnVtJ3UgVMOcTSByZW1vdGUnbGFyZGEgaGFyZC1yZWxvYWQnYSBrYWRhciBiaXIgZGFoYSDDp2VraWxlbWV6IHlhcGFyZMSxLiBsb2FkaW5nPWZhbHNlXHJcblx0XHRcdFx0Ly8g4oaSIHNvbnJha2kgZmV0Y2hFbnVtIChjb21wb25lbnQgaW5pdC9yZXRyeSkgeWVuaWRlbiBkZW5leWViaWxpci4gbG9hZGVkIHphdGVuIGZhbHNlIGthbMSxci5cclxuXHRcdFx0XHQvLyBEZW5lbWUgc2F5xLFzxLEgTUFYX0ZFVENIX0ZBSUxVUkVTIGlsZSBzxLFuxLFybMSxOiBrYWzEsWPEsSBoYXRhZGEgc29uc3V6IHJldHJ5IMO2bmxlbmlyLlxyXG5cdFx0XHRcdGVycm9yOiAoKSA9PiB7XHJcblx0XHRcdFx0XHR0aGlzLmxvYWRpbmcuc2V0KGtleSwgZmFsc2UpO1xyXG5cdFx0XHRcdFx0dGhpcy5mYWlsdXJlcy5zZXQoa2V5LCAodGhpcy5mYWlsdXJlcy5nZXQoa2V5KSA/PyAwKSArIDEpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fSk7XHJcblx0fVxyXG5cclxuXHQvLyBrZXkgZm9ybWF0xLE6IGBncm91cE5hbWV+cGFyZW50U2VsZWN0aW9uS2V5YCAoZmV0Y2hFbnVtJ2Rha2kgY29tcG9zaXRlIGtleSBpbGUgYXluxLEpLlxyXG5cdC8vIERpcmVrdCBvbGFyYWsgZ3JvdXBOYW1lIGdlw6dpbGlyc2UgTWFwJ3RlIGXFn2xlxZ9tZSBvbG1heiB2ZSBoZXIgemFtYW4gZmFsc2UgZMO2bmVyLlxyXG5cdGlzTG9hZGluZyhrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG5cdFx0cmV0dXJuIHRoaXMubG9hZGluZy5nZXQoa2V5KSA/PyBmYWxzZTtcclxuXHR9XHJcbn1cclxuIl19
|
|
@@ -36,6 +36,17 @@ class MfeBridge {
|
|
|
36
36
|
* navigation'ları otomatik tab-aware olur, Strategy doğru tab handle'ını korur.
|
|
37
37
|
*/
|
|
38
38
|
this.activeTabId = signal('');
|
|
39
|
+
/**
|
|
40
|
+
* Enum (SelectionGroup) cache — cross-MFE paylaşımlı. `SelectionGroupService` her MFE/tab'da
|
|
41
|
+
* ayrı instance olsa da (Module Federation shared yok) hepsi bu tek state üzerinden okur/yazar
|
|
42
|
+
* → tek enum cache, tek `/versions` çağrısı, MFE'ler arası localStorage ezme yok.
|
|
43
|
+
*/
|
|
44
|
+
this.selectionGroups = signal({});
|
|
45
|
+
this.selectionLoaded = new Map();
|
|
46
|
+
this.selectionLoading = new Map();
|
|
47
|
+
/** Key başına ardışık fetch hatası sayısı — limit aşımında fetchEnum o key'i denemeyi bırakır. */
|
|
48
|
+
this.selectionFailures = new Map();
|
|
49
|
+
this.selectionInitialized = false;
|
|
39
50
|
this.hostNgZone = null;
|
|
40
51
|
this.hostRouter = null;
|
|
41
52
|
/**
|
|
@@ -86,6 +97,12 @@ const bridge = (() => {
|
|
|
86
97
|
if (!g[BRIDGE_SLOT]) {
|
|
87
98
|
g[BRIDGE_SLOT] = new MfeBridge();
|
|
88
99
|
}
|
|
100
|
+
const backfill = g[BRIDGE_SLOT];
|
|
101
|
+
backfill.selectionGroups ??= signal({});
|
|
102
|
+
backfill.selectionLoaded ??= new Map();
|
|
103
|
+
backfill.selectionLoading ??= new Map();
|
|
104
|
+
backfill.selectionFailures ??= new Map();
|
|
105
|
+
backfill.selectionInitialized ??= false;
|
|
89
106
|
return g[BRIDGE_SLOT];
|
|
90
107
|
})();
|
|
91
108
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aril-boot-bridge.mjs","sources":["../../projects/aril/boot/bridge/src/mfe-bridge.ts","../../projects/aril/boot/bridge/src/provide-mfe-bridge.ts","../../projects/aril/boot/bridge/aril-boot-bridge.ts"],"sourcesContent":["import type { Location } from '@angular/common';\r\nimport { NgZone, Signal, effect, signal } from '@angular/core';\r\nimport type { Router } from '@angular/router';\r\n\r\nimport type { Apps, PluginMenuItem } from 'aril/boot/config/apps';\r\n\r\nexport interface RouteConfig {\r\n\tpath: string;\r\n\tcontent: string;\r\n\tversion: number;\r\n}\r\n\r\nexport interface Breadcrumb {\r\n\tlabel: string;\r\n\turl?: string;\r\n}\r\n\r\nexport interface LegacyWindowSlots {\r\n\tactiveHost?: Apps;\r\n\tactiveMF?: Apps;\r\n\thostMenuItems?: Signal<PluginMenuItem[]>;\r\n\tpluginJson?: Record<string, unknown>;\r\n\trouteConfigs?: RouteConfig[];\r\n\tngZone?: NgZone;\r\n\thostRouter?: Router;\r\n\t__ARIL_PAGE_TITLE__?: Signal<string>;\r\n}\r\n\r\nexport class MfeBridge {\r\n\treadonly activeHost = signal<Apps | null>(null);\r\n\treadonly activeMF = signal<Apps | null>(null);\r\n\treadonly hostMenuItems = signal<PluginMenuItem[]>([]);\r\n\treadonly pluginJson = signal<Record<string, unknown>>({});\r\n\treadonly routeConfigs = signal<RouteConfig[] | null>(null);\r\n\treadonly pageTitle = signal<string>('');\r\n\treadonly breadcrumbs = signal<Breadcrumb[]>([]);\r\n\t/**\r\n\t * Bir MFE Router'ında olan son `NavigationEnd`'in URL'i ve **hangi tab'a ait olduğu**.\r\n\t * MFE içi sayfa içi navigation'lar host Router'a yansımayabiliyor → `NavService` tab\r\n\t * navLink'ini güncellemek için bu signal'ı izler.\r\n\t *\r\n\t * **Neden tabId taşıyor**: Birden fazla tab'ın MFE Router'ı async event tetikleyebilir\r\n\t * (örn. hidden container'daki tab2 `?activeTab=1` replaceState yaparken). `activeTabId`'ye\r\n\t * bakarak update yaparsak yanlış tab'ı kontamine ederiz. Mesajda kaynak tabId'yi taşıyıp\r\n\t * `NavService.syncActiveTabNavLinkForTab(tabId, url)` ile spesifik tab'ı update ederiz.\r\n\t *\r\n\t * **Custom `equal`**: AppComponent her MFE NavigationEnd'de `set({tabId, url})` çağırır;\r\n\t * yeni object reference olduğu için default reference-equality re-emit eder. Bu durumda\r\n\t * aynı tab+url ile sürekli effect tetiklenir → tab navLink'i kullanıcının anasayfaya\r\n\t * geçtiği gibi (host route'lar MFE NavigationEnd tetiklemez ama signal eski değerinde\r\n\t * kalır) state değişikliklerini geri alır. Value-equality ile yalnızca gerçek URL\r\n\t * değişikliklerinde tetiklensin.\r\n\t */\r\n\treadonly activeMFEUrl = signal<{ tabId: string; url: string; title?: string } | null>(null, {\r\n\t\tequal: (a, b) => a?.tabId === b?.tabId && a?.url === b?.url && a?.title === b?.title\r\n\t});\r\n\r\n\t/**\r\n\t * Aktif tab'ın `tabId`'si — `NavService` tab değişimlerinde günceller.\r\n\t * Plugin Router proxy'leri (`provideHostRouter`) bu signal'ı okuyup `navigate`/`navigateByUrl`\r\n\t * çağrılarına `extras.state._tab` enjekte eder → plugin'lerin yaptığı tüm host\r\n\t * navigation'ları otomatik tab-aware olur, Strategy doğru tab handle'ını korur.\r\n\t */\r\n\treadonly activeTabId = signal<string>('');\r\n\r\n\thostNgZone: NgZone | null = null;\r\n\thostRouter: Router | null = null;\r\n\t/**\r\n\t * Host (shell) `Location` servisi. Host modda MFE/plugin child injector'larından\r\n\t * erişilemez (child Location izole `IsolatedLocationStrategy`'ye bağlı); browser\r\n\t * adres çubuğuna `replaceState` ile yazmak isteyen directive'ler (örn. `?activeTab`\r\n\t * senkronizasyonu) bunu kullanır. `hostRouter` ile aynı pattern.\r\n\t */\r\n\thostLocation: Location | null = null;\r\n\r\n\tprivate mirrored = false;\r\n\r\n\tmirrorToWindow(): void {\r\n\t\tif (this.mirrored || typeof window === 'undefined') return;\r\n\t\tthis.mirrored = true;\r\n\r\n\t\tconst w = window as Window & LegacyWindowSlots;\r\n\r\n\t\tw.hostMenuItems = this.hostMenuItems;\r\n\t\tw.__ARIL_PAGE_TITLE__ = this.pageTitle;\r\n\r\n\t\teffect(() => {\r\n\t\t\tw.activeHost = this.activeHost() ?? undefined;\r\n\t\t});\r\n\t\teffect(() => {\r\n\t\t\tw.activeMF = this.activeMF() ?? undefined;\r\n\t\t});\r\n\t\teffect(() => {\r\n\t\t\tw.pluginJson = this.pluginJson();\r\n\t\t});\r\n\t\teffect(() => {\r\n\t\t\tw.routeConfigs = this.routeConfigs() ?? undefined;\r\n\t\t});\r\n\r\n\t\tObject.defineProperty(w, 'ngZone', {\r\n\t\t\tconfigurable: true,\r\n\t\t\tget: () => this.hostNgZone\r\n\t\t});\r\n\t\tObject.defineProperty(w, 'hostRouter', {\r\n\t\t\tconfigurable: true,\r\n\t\t\tget: () => this.hostRouter\r\n\t\t});\r\n\t}\r\n}\r\n\r\n// Module Federation shared config olmadığı durumlar için globalThis slot\r\n// üzerinden tek instance garantisi. Host ve her remote MFE ayrı bundle olsa\r\n// bile aynı JS realm'inde aynı instance'ı okur — eski globalThis sözleşmesinin\r\n// yaptığı görevi tek bir tipli slotta birleştirir.\r\nconst BRIDGE_SLOT = '__arilMfeBridge__';\r\ntype BridgeSlotHost = { [BRIDGE_SLOT]?: MfeBridge };\r\nexport const bridge: MfeBridge = (() => {\r\n\tconst g = globalThis as unknown as BridgeSlotHost;\r\n\tif (!g[BRIDGE_SLOT]) {\r\n\t\tg[BRIDGE_SLOT] = new MfeBridge();\r\n\t}\r\n\treturn g[BRIDGE_SLOT]!;\r\n})();\r\n","import { makeEnvironmentProviders } from '@angular/core';\r\n\r\nimport { MfeBridge, bridge } from './mfe-bridge';\r\n\r\nexport function provideMfeBridge() {\r\n\treturn makeEnvironmentProviders([{ provide: MfeBridge, useValue: bridge }]);\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"aril-boot-bridge.mjs","sources":["../../projects/aril/boot/bridge/src/mfe-bridge.ts","../../projects/aril/boot/bridge/src/provide-mfe-bridge.ts","../../projects/aril/boot/bridge/aril-boot-bridge.ts"],"sourcesContent":["import type { Location } from '@angular/common';\r\nimport { NgZone, Signal, effect, signal } from '@angular/core';\r\nimport type { Router } from '@angular/router';\r\n\r\nimport type { Apps, PluginMenuItem } from 'aril/boot/config/apps';\r\n\r\nexport interface RouteConfig {\r\n\tpath: string;\r\n\tcontent: string;\r\n\tversion: number;\r\n}\r\n\r\nexport interface Breadcrumb {\r\n\tlabel: string;\r\n\turl?: string;\r\n}\r\n\r\n// Selection-group (enum) modeli — cache state (aşağıda `selectionGroups`) bridge'de yaşadığından\r\n// tipi de burada tanımlanır; `theme/layout` bu tipleri re-export eder (bridge↔theme/layout circular\r\n// entry-point'ini önlemek için bağımlılık tek yönlü: theme/layout → bridge).\r\nexport interface SelectionItem {\r\n\tid: number;\r\n\tgroupId: number;\r\n\tselectionKey: string;\r\n\tselectionDisplay: string;\r\n\tshowOrder: number;\r\n\tparentSelectionKey: string;\r\n\tselectionMultiLanguageDisplays?: Record<string, string>;\r\n}\r\n\r\nexport interface SelectionGroupDTO {\r\n\tid: number;\r\n\tgroupName: string;\r\n\tgroupDescription: string;\r\n\tgroupComment: string;\r\n\tloadStrategy: string;\r\n\tdynamicQuery: string;\r\n\tparentGroupId: number;\r\n\tselectionItems: SelectionItem[];\r\n\tversion?: number;\r\n}\r\n\r\nexport interface LegacyWindowSlots {\r\n\tactiveHost?: Apps;\r\n\tactiveMF?: Apps;\r\n\thostMenuItems?: Signal<PluginMenuItem[]>;\r\n\tpluginJson?: Record<string, unknown>;\r\n\trouteConfigs?: RouteConfig[];\r\n\tngZone?: NgZone;\r\n\thostRouter?: Router;\r\n\t__ARIL_PAGE_TITLE__?: Signal<string>;\r\n}\r\n\r\nexport class MfeBridge {\r\n\treadonly activeHost = signal<Apps | null>(null);\r\n\treadonly activeMF = signal<Apps | null>(null);\r\n\treadonly hostMenuItems = signal<PluginMenuItem[]>([]);\r\n\treadonly pluginJson = signal<Record<string, unknown>>({});\r\n\treadonly routeConfigs = signal<RouteConfig[] | null>(null);\r\n\treadonly pageTitle = signal<string>('');\r\n\treadonly breadcrumbs = signal<Breadcrumb[]>([]);\r\n\t/**\r\n\t * Bir MFE Router'ında olan son `NavigationEnd`'in URL'i ve **hangi tab'a ait olduğu**.\r\n\t * MFE içi sayfa içi navigation'lar host Router'a yansımayabiliyor → `NavService` tab\r\n\t * navLink'ini güncellemek için bu signal'ı izler.\r\n\t *\r\n\t * **Neden tabId taşıyor**: Birden fazla tab'ın MFE Router'ı async event tetikleyebilir\r\n\t * (örn. hidden container'daki tab2 `?activeTab=1` replaceState yaparken). `activeTabId`'ye\r\n\t * bakarak update yaparsak yanlış tab'ı kontamine ederiz. Mesajda kaynak tabId'yi taşıyıp\r\n\t * `NavService.syncActiveTabNavLinkForTab(tabId, url)` ile spesifik tab'ı update ederiz.\r\n\t *\r\n\t * **Custom `equal`**: AppComponent her MFE NavigationEnd'de `set({tabId, url})` çağırır;\r\n\t * yeni object reference olduğu için default reference-equality re-emit eder. Bu durumda\r\n\t * aynı tab+url ile sürekli effect tetiklenir → tab navLink'i kullanıcının anasayfaya\r\n\t * geçtiği gibi (host route'lar MFE NavigationEnd tetiklemez ama signal eski değerinde\r\n\t * kalır) state değişikliklerini geri alır. Value-equality ile yalnızca gerçek URL\r\n\t * değişikliklerinde tetiklensin.\r\n\t */\r\n\treadonly activeMFEUrl = signal<{ tabId: string; url: string; title?: string } | null>(null, {\r\n\t\tequal: (a, b) => a?.tabId === b?.tabId && a?.url === b?.url && a?.title === b?.title\r\n\t});\r\n\r\n\t/**\r\n\t * Aktif tab'ın `tabId`'si — `NavService` tab değişimlerinde günceller.\r\n\t * Plugin Router proxy'leri (`provideHostRouter`) bu signal'ı okuyup `navigate`/`navigateByUrl`\r\n\t * çağrılarına `extras.state._tab` enjekte eder → plugin'lerin yaptığı tüm host\r\n\t * navigation'ları otomatik tab-aware olur, Strategy doğru tab handle'ını korur.\r\n\t */\r\n\treadonly activeTabId = signal<string>('');\r\n\r\n\t/**\r\n\t * Enum (SelectionGroup) cache — cross-MFE paylaşımlı. `SelectionGroupService` her MFE/tab'da\r\n\t * ayrı instance olsa da (Module Federation shared yok) hepsi bu tek state üzerinden okur/yazar\r\n\t * → tek enum cache, tek `/versions` çağrısı, MFE'ler arası localStorage ezme yok.\r\n\t */\r\n\treadonly selectionGroups = signal<{ [key: string]: SelectionGroupDTO | null }>({});\r\n\treadonly selectionLoaded = new Map<string, boolean>();\r\n\treadonly selectionLoading = new Map<string, boolean>();\r\n\t/** Key başına ardışık fetch hatası sayısı — limit aşımında fetchEnum o key'i denemeyi bırakır. */\r\n\treadonly selectionFailures = new Map<string, number>();\r\n\tselectionInitialized = false;\r\n\r\n\thostNgZone: NgZone | null = null;\r\n\thostRouter: Router | null = null;\r\n\t/**\r\n\t * Host (shell) `Location` servisi. Host modda MFE/plugin child injector'larından\r\n\t * erişilemez (child Location izole `IsolatedLocationStrategy`'ye bağlı); browser\r\n\t * adres çubuğuna `replaceState` ile yazmak isteyen directive'ler (örn. `?activeTab`\r\n\t * senkronizasyonu) bunu kullanır. `hostRouter` ile aynı pattern.\r\n\t */\r\n\thostLocation: Location | null = null;\r\n\r\n\tprivate mirrored = false;\r\n\r\n\tmirrorToWindow(): void {\r\n\t\tif (this.mirrored || typeof window === 'undefined') return;\r\n\t\tthis.mirrored = true;\r\n\r\n\t\tconst w = window as Window & LegacyWindowSlots;\r\n\r\n\t\tw.hostMenuItems = this.hostMenuItems;\r\n\t\tw.__ARIL_PAGE_TITLE__ = this.pageTitle;\r\n\r\n\t\teffect(() => {\r\n\t\t\tw.activeHost = this.activeHost() ?? undefined;\r\n\t\t});\r\n\t\teffect(() => {\r\n\t\t\tw.activeMF = this.activeMF() ?? undefined;\r\n\t\t});\r\n\t\teffect(() => {\r\n\t\t\tw.pluginJson = this.pluginJson();\r\n\t\t});\r\n\t\teffect(() => {\r\n\t\t\tw.routeConfigs = this.routeConfigs() ?? undefined;\r\n\t\t});\r\n\r\n\t\tObject.defineProperty(w, 'ngZone', {\r\n\t\t\tconfigurable: true,\r\n\t\t\tget: () => this.hostNgZone\r\n\t\t});\r\n\t\tObject.defineProperty(w, 'hostRouter', {\r\n\t\t\tconfigurable: true,\r\n\t\t\tget: () => this.hostRouter\r\n\t\t});\r\n\t}\r\n}\r\n\r\n// Module Federation shared config olmadığı durumlar için globalThis slot\r\n// üzerinden tek instance garantisi. Host ve her remote MFE ayrı bundle olsa\r\n// bile aynı JS realm'inde aynı instance'ı okur — eski globalThis sözleşmesinin\r\n// yaptığı görevi tek bir tipli slotta birleştirir.\r\nconst BRIDGE_SLOT = '__arilMfeBridge__';\r\ntype BridgeSlotHost = { [BRIDGE_SLOT]?: MfeBridge };\r\n\r\n// Staggered deploy guard'ı için mutable görünüm: slot'u ESKİ bir aril build'inin MfeBridge'i\r\n// doldurmuş olabilir (app'ler ayrı repolardan bağımsız deploy edilir; alan listesi build'ler\r\n// arası genişler). Sonradan eklenen alanlar eski instance'ta yoktur → backfill edilmezse yeni\r\n// lib'li bundle ilk okumada TypeError alır. readonly compile-time kısıtı burada bilinçli aşılır.\r\ntype BridgeBackfill = {\r\n\tselectionGroups?: MfeBridge['selectionGroups'];\r\n\tselectionLoaded?: MfeBridge['selectionLoaded'];\r\n\tselectionLoading?: MfeBridge['selectionLoading'];\r\n\tselectionFailures?: MfeBridge['selectionFailures'];\r\n\tselectionInitialized?: boolean;\r\n};\r\n\r\nexport const bridge: MfeBridge = (() => {\r\n\tconst g = globalThis as unknown as BridgeSlotHost;\r\n\tif (!g[BRIDGE_SLOT]) {\r\n\t\tg[BRIDGE_SLOT] = new MfeBridge();\r\n\t}\r\n\r\n\tconst backfill = g[BRIDGE_SLOT] as unknown as BridgeBackfill;\r\n\tbackfill.selectionGroups ??= signal<{ [key: string]: SelectionGroupDTO | null }>({});\r\n\tbackfill.selectionLoaded ??= new Map<string, boolean>();\r\n\tbackfill.selectionLoading ??= new Map<string, boolean>();\r\n\tbackfill.selectionFailures ??= new Map<string, number>();\r\n\tbackfill.selectionInitialized ??= false;\r\n\r\n\treturn g[BRIDGE_SLOT]!;\r\n})();\r\n","import { makeEnvironmentProviders } from '@angular/core';\r\n\r\nimport { MfeBridge, bridge } from './mfe-bridge';\r\n\r\nexport function provideMfeBridge() {\r\n\treturn makeEnvironmentProviders([{ provide: MfeBridge, useValue: bridge }]);\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;MAqDa,SAAS,CAAA;AAAtB,IAAA,WAAA,GAAA;AACU,QAAA,IAAA,CAAA,UAAU,GAAG,MAAM,CAAc,IAAI,CAAC,CAAC;AACvC,QAAA,IAAA,CAAA,QAAQ,GAAG,MAAM,CAAc,IAAI,CAAC,CAAC;AACrC,QAAA,IAAA,CAAA,aAAa,GAAG,MAAM,CAAmB,EAAE,CAAC,CAAC;AAC7C,QAAA,IAAA,CAAA,UAAU,GAAG,MAAM,CAA0B,EAAE,CAAC,CAAC;AACjD,QAAA,IAAA,CAAA,YAAY,GAAG,MAAM,CAAuB,IAAI,CAAC,CAAC;AAClD,QAAA,IAAA,CAAA,SAAS,GAAG,MAAM,CAAS,EAAE,CAAC,CAAC;AAC/B,QAAA,IAAA,CAAA,WAAW,GAAG,MAAM,CAAe,EAAE,CAAC,CAAC;AAChD;;;;;;;;;;;;;;;;AAgBG;AACM,QAAA,IAAA,CAAA,YAAY,GAAG,MAAM,CAAwD,IAAI,EAAE;AAC3F,YAAA,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,KAAK;AACpF,SAAA,CAAC,CAAC;AAEH;;;;;AAKG;AACM,QAAA,IAAA,CAAA,WAAW,GAAG,MAAM,CAAS,EAAE,CAAC,CAAC;AAE1C;;;;AAIG;AACM,QAAA,IAAA,CAAA,eAAe,GAAG,MAAM,CAA8C,EAAE,CAAC,CAAC;AAC1E,QAAA,IAAA,CAAA,eAAe,GAAG,IAAI,GAAG,EAAmB,CAAC;AAC7C,QAAA,IAAA,CAAA,gBAAgB,GAAG,IAAI,GAAG,EAAmB,CAAC;;AAE9C,QAAA,IAAA,CAAA,iBAAiB,GAAG,IAAI,GAAG,EAAkB,CAAC;QACvD,IAAoB,CAAA,oBAAA,GAAG,KAAK,CAAC;QAE7B,IAAU,CAAA,UAAA,GAAkB,IAAI,CAAC;QACjC,IAAU,CAAA,UAAA,GAAkB,IAAI,CAAC;AACjC;;;;;AAKG;QACH,IAAY,CAAA,YAAA,GAAoB,IAAI,CAAC;QAE7B,IAAQ,CAAA,QAAA,GAAG,KAAK,CAAC;KAiCzB;IA/BA,cAAc,GAAA;AACb,QAAA,IAAI,IAAI,CAAC,QAAQ,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO;AAC3D,QAAA,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QAErB,MAAM,CAAC,GAAG,MAAoC,CAAC;AAE/C,QAAA,CAAC,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;AACrC,QAAA,CAAC,CAAC,mBAAmB,GAAG,IAAI,CAAC,SAAS,CAAC;QAEvC,MAAM,CAAC,MAAK;YACX,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,SAAS,CAAC;AAC/C,SAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAK;YACX,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,SAAS,CAAC;AAC3C,SAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAK;AACX,YAAA,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;AAClC,SAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAK;YACX,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,SAAS,CAAC;AACnD,SAAC,CAAC,CAAC;AAEH,QAAA,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,QAAQ,EAAE;AAClC,YAAA,YAAY,EAAE,IAAI;AAClB,YAAA,GAAG,EAAE,MAAM,IAAI,CAAC,UAAU;AAC1B,SAAA,CAAC,CAAC;AACH,QAAA,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,YAAY,EAAE;AACtC,YAAA,YAAY,EAAE,IAAI;AAClB,YAAA,GAAG,EAAE,MAAM,IAAI,CAAC,UAAU;AAC1B,SAAA,CAAC,CAAC;KACH;AACD,CAAA;AAED;AACA;AACA;AACA;AACA,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAe3B,MAAA,MAAM,GAAc,CAAC,MAAK;IACtC,MAAM,CAAC,GAAG,UAAuC,CAAC;AAClD,IAAA,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE;AACpB,QAAA,CAAC,CAAC,WAAW,CAAC,GAAG,IAAI,SAAS,EAAE,CAAC;KACjC;AAED,IAAA,MAAM,QAAQ,GAAG,CAAC,CAAC,WAAW,CAA8B,CAAC;AAC7D,IAAA,QAAQ,CAAC,eAAe,KAAK,MAAM,CAA8C,EAAE,CAAC,CAAC;AACrF,IAAA,QAAQ,CAAC,eAAe,KAAK,IAAI,GAAG,EAAmB,CAAC;AACxD,IAAA,QAAQ,CAAC,gBAAgB,KAAK,IAAI,GAAG,EAAmB,CAAC;AACzD,IAAA,QAAQ,CAAC,iBAAiB,KAAK,IAAI,GAAG,EAAkB,CAAC;AACzD,IAAA,QAAQ,CAAC,oBAAoB,KAAK,KAAK,CAAC;AAExC,IAAA,OAAO,CAAC,CAAC,WAAW,CAAE,CAAC;AACxB,CAAC;;SChLe,gBAAgB,GAAA;AAC/B,IAAA,OAAO,wBAAwB,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;AAC7E;;ACNA;;AAEG;;;;"}
|
|
@@ -8,7 +8,7 @@ import { ModuleFederationToolsModule } from '@angular-architects/module-federati
|
|
|
8
8
|
import { safeNavigate } from 'aril/boot/config/apps';
|
|
9
9
|
import { LanguageCode, TR_TRANSLATIONS } from 'aril/boot/config/translate';
|
|
10
10
|
import { BreadcrumbService, MFELayoutComponent } from 'aril/theme/layout';
|
|
11
|
-
import { a as appName } from './aril-boot-mfe-aril-boot-mfe-
|
|
11
|
+
import { a as appName } from './aril-boot-mfe-aril-boot-mfe-CKOM61xb.mjs';
|
|
12
12
|
import * as i2 from '@ngneat/transloco';
|
|
13
13
|
import * as i3 from 'primeng/api';
|
|
14
14
|
import * as i4 from 'aril/boot/bridge';
|
|
@@ -180,4 +180,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImpor
|
|
|
180
180
|
}], ctorParameters: () => [{ type: i1.Router }, { type: i2.TranslocoService }, { type: i3.PrimeNGConfig }, { type: i4.MfeBridge }] });
|
|
181
181
|
|
|
182
182
|
export { AppComponent };
|
|
183
|
-
//# sourceMappingURL=aril-boot-mfe-app.component-
|
|
183
|
+
//# sourceMappingURL=aril-boot-mfe-app.component-oxzMhRXe.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aril-boot-mfe-app.component-a34GeuUv.mjs","sources":["../../projects/aril/boot/mfe/src/app.component.ts"],"sourcesContent":["import { LocationStrategy } from '@angular/common';\r\nimport { Component, ElementRef, effect, inject } from '@angular/core';\r\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\r\nimport { EventType, Router, type Event as RouterEvent } from '@angular/router';\r\n\r\nimport { PrimeNGConfig } from 'primeng/api';\r\n\r\nimport { ModuleFederationToolsModule } from '@angular-architects/module-federation-tools';\r\nimport { TranslocoService } from '@ngneat/transloco';\r\n\r\nimport { MfeBridge } from 'aril/boot/bridge';\r\nimport { safeNavigate } from 'aril/boot/config/apps';\r\nimport { LanguageCode, TR_TRANSLATIONS } from 'aril/boot/config/translate';\r\nimport { BreadcrumbService, MFELayoutComponent } from 'aril/theme/layout';\r\n\r\nimport { appName } from './bootstrap';\r\n\r\n/**\r\n * Tab izolasyonlu MFE app root.\r\n *\r\n * Her `<app-${appName}>` custom element instance'ı kendi `createApplication`'ını yarattığı için\r\n * (bkz. `bootstrap.ts` `MFEAppElement`), `AppComponent` constructor'ı her tab için **bağımsız**\r\n * çalışır — paylaşılan Injector/Router yok. Bu yüzden host Router subscription'ı her tab için\r\n * ayrı kurulur ama \"tab-id filter\" ile **sadece o tab'a ait** `NavigationEnd`'leri MFE Router'a\r\n * iletir; diğer tab'lerin navigation'ları ignore edilir.\r\n *\r\n * Tab kimliği `<app-${appName}>` element'inde `aril-tab-id` attribute olarak yazılır\r\n * (`ArilWebComponentWrapper` route.queryParams._tab'ten okuyup set eder). Filter karşılaştırması:\r\n * `window.history.state._tab === tabId` — `navigateToTab` `extras.state._tab` ile yazıyor.\r\n */\r\n@Component({\r\n\tstandalone: true,\r\n\ttemplate: `<mfe-layout></mfe-layout>`,\r\n\timports: [ModuleFederationToolsModule, MFELayoutComponent]\r\n})\r\nexport class AppComponent {\r\n\tprivate readonly elementRef = inject(ElementRef);\r\n\r\n\tconstructor(\r\n\t\tprivate readonly router: Router,\r\n\t\tprivate readonly translocoService: TranslocoService,\r\n\t\tprivate readonly primeNgConfig: PrimeNGConfig,\r\n\t\tprivate readonly bridgeSvc: MfeBridge\r\n\t) {\r\n\t\t// Bu tab'ın kimliği — wrapper component `aril-tab-id` attribute olarak yazıyor.\r\n\t\t// İlk yükleme cycle'ında URL'de henüz `_tab` yok; NavService `firstCheckForRoute`\r\n\t\t// sonradan `replaceUrl` ile ekliyor. Wrapper queryParams.subscribe ile attribute'u\r\n\t\t// güncelliyor — bu yüzden constructor'da değil, her NavigationEnd'de fresh okuyoruz.\r\n\t\tconst readMyTabId = (): string => (this.elementRef.nativeElement as HTMLElement).getAttribute('aril-tab-id') ?? '';\r\n\r\n\t\tconst initialTabId = readMyTabId();\r\n\t\tconst locStrategy = inject(LocationStrategy);\r\n\t\tconst sameRouter = this.router === this.bridgeSvc.hostRouter;\r\n\t\tconsole.log(\r\n\t\t\t`[MFE:${appName}] host modu — tab=\"${initialTabId || '(pending)'}\" ` +\r\n\t\t\t\t`LocationStrategy=${locStrategy.constructor.name} ` +\r\n\t\t\t\t`router===hostRouter? ${sameRouter}`\r\n\t\t);\r\n\t\tconst initial = this.bridgeSvc.hostRouter!.url;\r\n\t\tconsole.log(`[MFE:${appName}] initial sync:`, initial);\r\n\t\tsafeNavigate(this.router, initial);\r\n\r\n\t\t// MFE içi `routerLink`/`router.navigate` host Router'a yansımıyor (IsolatedLocationStrategy\r\n\t\t// browser hash'ı değiştirmiyor) — NavService tab navLink'ini güncelleyemiyor.\r\n\t\t// MFE NavigationEnd'i `bridge.activeMFEUrl`'a (kaynak tabId ile) yazarız;\r\n\t\t// AppLayoutComponent effect → `syncActiveTabNavLinkForTab(tabId, url)` ile sadece\r\n\t\t// kaynak tab'ın navLink'i güncellenir → cross-tab kontaminasyonu yok.\r\n\t\t// Tab title resolve — kaynak öncelik sırası (en spesifik → en geniş):\r\n\t\t// 1. `route.title` (ÖNERİLEN — Angular Router 16+ standardı, sayfa <title>'ını da set eder)\r\n\t\t// 2. `data.tabName` (ÖNERİLEN — tab adı sayfa <title>'ından farklı olmalıysa)\r\n\t\t// 3. `data.title` (DEPRECATED — geriye uyumluluk için var; yeni route'larda kullanmayın,\r\n\t\t// `route.title` ile aynı semantiği taşıyor ama Angular contract dışı kalıyor)\r\n\t\t// 4. `data.breadcrumb` — mevcut breadcrumb template'i fallback olarak kullanılır\r\n\t\t// (single-brace `{key}` placeholder, literal string, i18n YOK)\r\n\t\t//\r\n\t\t// i18n key'lerinde `{{placeholder}}` Transloco interpolation'ı `BreadcrumbService.keyValues`\r\n\t\t// ile doldurulur. Component cevap geldiğinde `breadcrumbService.set('GatewayMaterialSerialNumber',\r\n\t\t// '12345')` her iki path'i de besler — effect ile re-compute, dinamik tab adı\r\n\t\t// (\"12345 - Modem Detay\").\r\n\t\tconst breadcrumbService = inject(BreadcrumbService);\r\n\t\tconst computeTabTitle = (): string | undefined => {\r\n\t\t\tlet route = this.router.routerState.snapshot.root;\r\n\t\t\twhile (route.firstChild) route = route.firstChild;\r\n\t\t\tconst params = breadcrumbService.keyValues();\r\n\r\n\t\t\tconst i18nKey =\r\n\t\t\t\t(route.title as string | undefined) ??\r\n\t\t\t\t(route.data?.['title'] as string | undefined) ??\r\n\t\t\t\t(route.data?.['tabName'] as string | undefined);\r\n\t\t\tif (i18nKey) {\r\n\t\t\t\tconst translated = this.translocoService.translate(i18nKey, params);\r\n\t\t\t\treturn translated || i18nKey;\r\n\t\t\t}\r\n\r\n\t\t\tconst breadcrumb = route.data?.['breadcrumb'] as string | undefined;\r\n\t\t\tif (breadcrumb) {\r\n\t\t\t\treturn breadcrumb.replace(/\\{([^}]+)\\}/g, (_, key: string) => params[key] ?? '...');\r\n\t\t\t}\r\n\r\n\t\t\treturn undefined;\r\n\t\t};\r\n\r\n\t\tlet lastUrl: string | undefined;\r\n\t\tlet lastTabIdForTitle: string | undefined;\r\n\r\n\t\tthis.router.events.pipe(takeUntilDestroyed()).subscribe((event: RouterEvent) => {\r\n\t\t\tif (event.type === EventType.NavigationEnd) {\r\n\t\t\t\tconst url = event.urlAfterRedirects ?? event.url;\r\n\t\t\t\tconst myTabId = readMyTabId();\r\n\t\t\t\tif (!myTabId) return;\r\n\t\t\t\tlastUrl = url;\r\n\t\t\t\tlastTabIdForTitle = myTabId;\r\n\t\t\t\tconst title = computeTabTitle();\r\n\t\t\t\tconst prev = this.bridgeSvc.activeMFEUrl();\r\n\t\t\t\tif (prev?.tabId === myTabId && prev?.url === url && prev?.title === title) return;\r\n\t\t\t\tthis.bridgeSvc.activeMFEUrl.set({ tabId: myTabId, url, title });\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\t// Component cevap gelince `breadcrumbService.set('meterNo', '12345')` keyValues'ı\r\n\t\t// günceller; effect ile yakalayıp tab title'ı yeniden hesaplarız → \"12345 - Sayaç\r\n\t\t// Detayı\" gibi dinamik sonuçlar tab adına yansır.\r\n\t\teffect(\r\n\t\t\t() => {\r\n\t\t\t\tbreadcrumbService.keyValues();\r\n\t\t\t\tif (!lastUrl || !lastTabIdForTitle) return;\r\n\t\t\t\tconst title = computeTabTitle();\r\n\t\t\t\tconst prev = this.bridgeSvc.activeMFEUrl();\r\n\t\t\t\tif (prev?.tabId === lastTabIdForTitle && prev?.url === lastUrl && prev?.title === title) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tthis.bridgeSvc.activeMFEUrl.set({ tabId: lastTabIdForTitle, url: lastUrl, title });\r\n\t\t\t},\r\n\t\t\t{ allowSignalWrites: true }\r\n\t\t);\r\n\r\n\t\tconst mfePrefix = `/${appName}`;\r\n\r\n\t\tthis.bridgeSvc.hostRouter!.events.pipe(takeUntilDestroyed()).subscribe((event: RouterEvent) => {\r\n\t\t\tif (event.type === EventType.NavigationEnd) {\r\n\t\t\t\tconst target = event.urlAfterRedirects ?? event.url;\r\n\t\t\t\tif (target !== mfePrefix && !target.startsWith(`${mfePrefix}/`)) return;\r\n\t\t\t\t// **Tab izolasyonu filter**: navigation'ın hedef tab'ı bu instance mı?\r\n\t\t\t\t// `IsolatedLocationStrategy` sayesinde host'a sadece tab tıklamaları\r\n\t\t\t\t// (`tabState({_tab})` ile) gelir — `history.state._tab` her zaman dolu.\r\n\t\t\t\tconst myTabId = readMyTabId();\r\n\t\t\t\tif (myTabId) {\r\n\t\t\t\t\tconst navTabId = (window.history.state as Record<string, unknown> | null)?.['_tab'];\r\n\t\t\t\t\tif (navTabId !== myTabId) return;\r\n\t\t\t\t}\r\n\t\t\t\t// `lastNavigated`/`router.url===target` early-return YOK: izole Router'da (her tab\r\n\t\t\t\t// kendi Router'ı) bir tab'a geri dönüldüğünde MFE Router zaten hedef URL'dedir;\r\n\t\t\t\t// navigate atlanırsa NavigationEnd fire etmez → `BreadcrumbPublisherService` yeniden\r\n\t\t\t\t// yayın yapmaz ve app.layout tab geçişinde breadcrumb'ı `set([])` ile temizlediği için\r\n\t\t\t\t// breadcrumb boş kalır. `onSameUrlNavigation:'reload'` aynı URL'e navigate'i\r\n\t\t\t\t// NavigationEnd ile garanti eder → breadcrumb + tab navLink yeniden yayınlanır.\r\n\t\t\t\tconsole.log(`[MFE:${appName}] tab=\"${myTabId || '(pending)'}\" host NavigationEnd → navigate:`, target);\r\n\t\t\t\tsafeNavigate(this.router, target);\r\n\t\t\t} else if (event.type === EventType.NavigationCancel) {\r\n\t\t\t\tconsole.warn(`[MFE:${appName}] host NavigationCancel:`, event.url, 'reason:', event.reason);\r\n\t\t\t} else if (event.type === EventType.NavigationError) {\r\n\t\t\t\tconsole.error(`[MFE:${appName}] host NavigationError:`, event.url, 'err:', event.error);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tthis.bridgeSvc.activeMF.set(appName);\r\n\t\tconst lang: LanguageCode = (localStorage.getItem('lang') as LanguageCode) ?? LanguageCode.TR;\r\n\r\n\t\tthis.translocoService.setActiveLang(lang);\r\n\r\n\t\tthis.setLocale(lang);\r\n\t}\r\n\r\n\tsetLocale(lang: LanguageCode) {\r\n\t\tif (!lang?.length) return;\r\n\r\n\t\tif (lang === LanguageCode.TR) {\r\n\t\t\tthis.primeNgConfig.setTranslation(TR_TRANSLATIONS);\r\n\t\t}\r\n\t}\r\n}\r\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAiBA;;;;;;;;;;;;AAYG;MAMU,YAAY,CAAA;AAGxB,IAAA,WAAA,CACkB,MAAc,EACd,gBAAkC,EAClC,aAA4B,EAC5B,SAAoB,EAAA;QAHpB,IAAM,CAAA,MAAA,GAAN,MAAM,CAAQ;QACd,IAAgB,CAAA,gBAAA,GAAhB,gBAAgB,CAAkB;QAClC,IAAa,CAAA,aAAA,GAAb,aAAa,CAAe;QAC5B,IAAS,CAAA,SAAA,GAAT,SAAS,CAAW;AANrB,QAAA,IAAA,CAAA,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;;;;;AAYhD,QAAA,MAAM,WAAW,GAAG,MAAe,IAAI,CAAC,UAAU,CAAC,aAA6B,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;AAEnH,QAAA,MAAM,YAAY,GAAG,WAAW,EAAE,CAAC;AACnC,QAAA,MAAM,WAAW,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;QAC7D,OAAO,CAAC,GAAG,CACV,CAAA,KAAA,EAAQ,OAAO,CAAsB,mBAAA,EAAA,YAAY,IAAI,WAAW,CAAI,EAAA,CAAA;AACnE,YAAA,CAAA,iBAAA,EAAoB,WAAW,CAAC,WAAW,CAAC,IAAI,CAAG,CAAA,CAAA;YACnD,CAAwB,qBAAA,EAAA,UAAU,CAAE,CAAA,CACrC,CAAC;QACF,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,UAAW,CAAC,GAAG,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,CAAA,KAAA,EAAQ,OAAO,CAAiB,eAAA,CAAA,EAAE,OAAO,CAAC,CAAC;AACvD,QAAA,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;;;;;;;;;;;;;;;;AAmBnC,QAAA,MAAM,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACpD,MAAM,eAAe,GAAG,MAAyB;YAChD,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC;YAClD,OAAO,KAAK,CAAC,UAAU;AAAE,gBAAA,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC;AAClD,YAAA,MAAM,MAAM,GAAG,iBAAiB,CAAC,SAAS,EAAE,CAAC;AAE7C,YAAA,MAAM,OAAO,GACX,KAAK,CAAC,KAA4B;AAClC,gBAAA,KAAK,CAAC,IAAI,GAAG,OAAO,CAAwB;AAC5C,gBAAA,KAAK,CAAC,IAAI,GAAG,SAAS,CAAwB,CAAC;YACjD,IAAI,OAAO,EAAE;AACZ,gBAAA,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBACpE,OAAO,UAAU,IAAI,OAAO,CAAC;aAC7B;YAED,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,GAAG,YAAY,CAAuB,CAAC;YACpE,IAAI,UAAU,EAAE;gBACf,OAAO,UAAU,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,GAAW,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC;aACpF;AAED,YAAA,OAAO,SAAS,CAAC;AAClB,SAAC,CAAC;AAEF,QAAA,IAAI,OAA2B,CAAC;AAChC,QAAA,IAAI,iBAAqC,CAAC;AAE1C,QAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,KAAkB,KAAI;YAC9E,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,aAAa,EAAE;gBAC3C,MAAM,GAAG,GAAG,KAAK,CAAC,iBAAiB,IAAI,KAAK,CAAC,GAAG,CAAC;AACjD,gBAAA,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;AAC9B,gBAAA,IAAI,CAAC,OAAO;oBAAE,OAAO;gBACrB,OAAO,GAAG,GAAG,CAAC;gBACd,iBAAiB,GAAG,OAAO,CAAC;AAC5B,gBAAA,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;gBAChC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC;AAC3C,gBAAA,IAAI,IAAI,EAAE,KAAK,KAAK,OAAO,IAAI,IAAI,EAAE,GAAG,KAAK,GAAG,IAAI,IAAI,EAAE,KAAK,KAAK,KAAK;oBAAE,OAAO;AAClF,gBAAA,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;aAChE;AACF,SAAC,CAAC,CAAC;;;;QAKH,MAAM,CACL,MAAK;YACJ,iBAAiB,CAAC,SAAS,EAAE,CAAC;AAC9B,YAAA,IAAI,CAAC,OAAO,IAAI,CAAC,iBAAiB;gBAAE,OAAO;AAC3C,YAAA,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC;AAC3C,YAAA,IAAI,IAAI,EAAE,KAAK,KAAK,iBAAiB,IAAI,IAAI,EAAE,GAAG,KAAK,OAAO,IAAI,IAAI,EAAE,KAAK,KAAK,KAAK,EAAE;gBACxF,OAAO;aACP;AACD,YAAA,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;AACpF,SAAC,EACD,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAC3B,CAAC;AAEF,QAAA,MAAM,SAAS,GAAG,CAAI,CAAA,EAAA,OAAO,EAAE,CAAC;AAEhC,QAAA,IAAI,CAAC,SAAS,CAAC,UAAW,CAAC,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,KAAkB,KAAI;YAC7F,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,aAAa,EAAE;gBAC3C,MAAM,MAAM,GAAG,KAAK,CAAC,iBAAiB,IAAI,KAAK,CAAC,GAAG,CAAC;AACpD,gBAAA,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA,EAAG,SAAS,CAAA,CAAA,CAAG,CAAC;oBAAE,OAAO;;;;AAIxE,gBAAA,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;gBAC9B,IAAI,OAAO,EAAE;oBACZ,MAAM,QAAQ,GAAI,MAAM,CAAC,OAAO,CAAC,KAAwC,GAAG,MAAM,CAAC,CAAC;oBACpF,IAAI,QAAQ,KAAK,OAAO;wBAAE,OAAO;iBACjC;;;;;;;AAOD,gBAAA,OAAO,CAAC,GAAG,CAAC,CAAA,KAAA,EAAQ,OAAO,CAAA,OAAA,EAAU,OAAO,IAAI,WAAW,CAAA,gCAAA,CAAkC,EAAE,MAAM,CAAC,CAAC;AACvG,gBAAA,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;aAClC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,gBAAgB,EAAE;AACrD,gBAAA,OAAO,CAAC,IAAI,CAAC,CAAQ,KAAA,EAAA,OAAO,0BAA0B,EAAE,KAAK,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;aAC5F;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,eAAe,EAAE;AACpD,gBAAA,OAAO,CAAC,KAAK,CAAC,CAAQ,KAAA,EAAA,OAAO,yBAAyB,EAAE,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;aACxF;AACF,SAAC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACrC,QAAA,MAAM,IAAI,GAAkB,YAAY,CAAC,OAAO,CAAC,MAAM,CAAkB,IAAI,YAAY,CAAC,EAAE,CAAC;AAE7F,QAAA,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;AAE1C,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;KACrB;AAED,IAAA,SAAS,CAAC,IAAkB,EAAA;QAC3B,IAAI,CAAC,IAAI,EAAE,MAAM;YAAE,OAAO;AAE1B,QAAA,IAAI,IAAI,KAAK,YAAY,CAAC,EAAE,EAAE;AAC7B,YAAA,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;SACnD;KACD;8GAhJW,YAAY,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,MAAA,EAAA,EAAA,EAAA,KAAA,EAAA,EAAA,CAAA,gBAAA,EAAA,EAAA,EAAA,KAAA,EAAA,EAAA,CAAA,aAAA,EAAA,EAAA,EAAA,KAAA,EAAA,EAAA,CAAA,SAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA,EAAA;AAAZ,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAY,EAHd,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,cAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAAA,CAAA,yBAAA,CAA2B,EAC3B,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,2BAA2B,+BAAE,kBAAkB,EAAA,QAAA,EAAA,YAAA,EAAA,CAAA,EAAA,CAAA,CAAA,EAAA;;2FAE7C,YAAY,EAAA,UAAA,EAAA,CAAA;kBALxB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE,IAAI;AAChB,oBAAA,QAAQ,EAAE,CAA2B,yBAAA,CAAA;AACrC,oBAAA,OAAO,EAAE,CAAC,2BAA2B,EAAE,kBAAkB,CAAC;AAC1D,iBAAA,CAAA;;;;;"}
|
|
1
|
+
{"version":3,"file":"aril-boot-mfe-app.component-oxzMhRXe.mjs","sources":["../../projects/aril/boot/mfe/src/app.component.ts"],"sourcesContent":["import { LocationStrategy } from '@angular/common';\r\nimport { Component, ElementRef, effect, inject } from '@angular/core';\r\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\r\nimport { EventType, Router, type Event as RouterEvent } from '@angular/router';\r\n\r\nimport { PrimeNGConfig } from 'primeng/api';\r\n\r\nimport { ModuleFederationToolsModule } from '@angular-architects/module-federation-tools';\r\nimport { TranslocoService } from '@ngneat/transloco';\r\n\r\nimport { MfeBridge } from 'aril/boot/bridge';\r\nimport { safeNavigate } from 'aril/boot/config/apps';\r\nimport { LanguageCode, TR_TRANSLATIONS } from 'aril/boot/config/translate';\r\nimport { BreadcrumbService, MFELayoutComponent } from 'aril/theme/layout';\r\n\r\nimport { appName } from './bootstrap';\r\n\r\n/**\r\n * Tab izolasyonlu MFE app root.\r\n *\r\n * Her `<app-${appName}>` custom element instance'ı kendi `createApplication`'ını yarattığı için\r\n * (bkz. `bootstrap.ts` `MFEAppElement`), `AppComponent` constructor'ı her tab için **bağımsız**\r\n * çalışır — paylaşılan Injector/Router yok. Bu yüzden host Router subscription'ı her tab için\r\n * ayrı kurulur ama \"tab-id filter\" ile **sadece o tab'a ait** `NavigationEnd`'leri MFE Router'a\r\n * iletir; diğer tab'lerin navigation'ları ignore edilir.\r\n *\r\n * Tab kimliği `<app-${appName}>` element'inde `aril-tab-id` attribute olarak yazılır\r\n * (`ArilWebComponentWrapper` route.queryParams._tab'ten okuyup set eder). Filter karşılaştırması:\r\n * `window.history.state._tab === tabId` — `navigateToTab` `extras.state._tab` ile yazıyor.\r\n */\r\n@Component({\r\n\tstandalone: true,\r\n\ttemplate: `<mfe-layout></mfe-layout>`,\r\n\timports: [ModuleFederationToolsModule, MFELayoutComponent]\r\n})\r\nexport class AppComponent {\r\n\tprivate readonly elementRef = inject(ElementRef);\r\n\r\n\tconstructor(\r\n\t\tprivate readonly router: Router,\r\n\t\tprivate readonly translocoService: TranslocoService,\r\n\t\tprivate readonly primeNgConfig: PrimeNGConfig,\r\n\t\tprivate readonly bridgeSvc: MfeBridge\r\n\t) {\r\n\t\t// Bu tab'ın kimliği — wrapper component `aril-tab-id` attribute olarak yazıyor.\r\n\t\t// İlk yükleme cycle'ında URL'de henüz `_tab` yok; NavService `firstCheckForRoute`\r\n\t\t// sonradan `replaceUrl` ile ekliyor. Wrapper queryParams.subscribe ile attribute'u\r\n\t\t// güncelliyor — bu yüzden constructor'da değil, her NavigationEnd'de fresh okuyoruz.\r\n\t\tconst readMyTabId = (): string => (this.elementRef.nativeElement as HTMLElement).getAttribute('aril-tab-id') ?? '';\r\n\r\n\t\tconst initialTabId = readMyTabId();\r\n\t\tconst locStrategy = inject(LocationStrategy);\r\n\t\tconst sameRouter = this.router === this.bridgeSvc.hostRouter;\r\n\t\tconsole.log(\r\n\t\t\t`[MFE:${appName}] host modu — tab=\"${initialTabId || '(pending)'}\" ` +\r\n\t\t\t\t`LocationStrategy=${locStrategy.constructor.name} ` +\r\n\t\t\t\t`router===hostRouter? ${sameRouter}`\r\n\t\t);\r\n\t\tconst initial = this.bridgeSvc.hostRouter!.url;\r\n\t\tconsole.log(`[MFE:${appName}] initial sync:`, initial);\r\n\t\tsafeNavigate(this.router, initial);\r\n\r\n\t\t// MFE içi `routerLink`/`router.navigate` host Router'a yansımıyor (IsolatedLocationStrategy\r\n\t\t// browser hash'ı değiştirmiyor) — NavService tab navLink'ini güncelleyemiyor.\r\n\t\t// MFE NavigationEnd'i `bridge.activeMFEUrl`'a (kaynak tabId ile) yazarız;\r\n\t\t// AppLayoutComponent effect → `syncActiveTabNavLinkForTab(tabId, url)` ile sadece\r\n\t\t// kaynak tab'ın navLink'i güncellenir → cross-tab kontaminasyonu yok.\r\n\t\t// Tab title resolve — kaynak öncelik sırası (en spesifik → en geniş):\r\n\t\t// 1. `route.title` (ÖNERİLEN — Angular Router 16+ standardı, sayfa <title>'ını da set eder)\r\n\t\t// 2. `data.tabName` (ÖNERİLEN — tab adı sayfa <title>'ından farklı olmalıysa)\r\n\t\t// 3. `data.title` (DEPRECATED — geriye uyumluluk için var; yeni route'larda kullanmayın,\r\n\t\t// `route.title` ile aynı semantiği taşıyor ama Angular contract dışı kalıyor)\r\n\t\t// 4. `data.breadcrumb` — mevcut breadcrumb template'i fallback olarak kullanılır\r\n\t\t// (single-brace `{key}` placeholder, literal string, i18n YOK)\r\n\t\t//\r\n\t\t// i18n key'lerinde `{{placeholder}}` Transloco interpolation'ı `BreadcrumbService.keyValues`\r\n\t\t// ile doldurulur. Component cevap geldiğinde `breadcrumbService.set('GatewayMaterialSerialNumber',\r\n\t\t// '12345')` her iki path'i de besler — effect ile re-compute, dinamik tab adı\r\n\t\t// (\"12345 - Modem Detay\").\r\n\t\tconst breadcrumbService = inject(BreadcrumbService);\r\n\t\tconst computeTabTitle = (): string | undefined => {\r\n\t\t\tlet route = this.router.routerState.snapshot.root;\r\n\t\t\twhile (route.firstChild) route = route.firstChild;\r\n\t\t\tconst params = breadcrumbService.keyValues();\r\n\r\n\t\t\tconst i18nKey =\r\n\t\t\t\t(route.title as string | undefined) ??\r\n\t\t\t\t(route.data?.['title'] as string | undefined) ??\r\n\t\t\t\t(route.data?.['tabName'] as string | undefined);\r\n\t\t\tif (i18nKey) {\r\n\t\t\t\tconst translated = this.translocoService.translate(i18nKey, params);\r\n\t\t\t\treturn translated || i18nKey;\r\n\t\t\t}\r\n\r\n\t\t\tconst breadcrumb = route.data?.['breadcrumb'] as string | undefined;\r\n\t\t\tif (breadcrumb) {\r\n\t\t\t\treturn breadcrumb.replace(/\\{([^}]+)\\}/g, (_, key: string) => params[key] ?? '...');\r\n\t\t\t}\r\n\r\n\t\t\treturn undefined;\r\n\t\t};\r\n\r\n\t\tlet lastUrl: string | undefined;\r\n\t\tlet lastTabIdForTitle: string | undefined;\r\n\r\n\t\tthis.router.events.pipe(takeUntilDestroyed()).subscribe((event: RouterEvent) => {\r\n\t\t\tif (event.type === EventType.NavigationEnd) {\r\n\t\t\t\tconst url = event.urlAfterRedirects ?? event.url;\r\n\t\t\t\tconst myTabId = readMyTabId();\r\n\t\t\t\tif (!myTabId) return;\r\n\t\t\t\tlastUrl = url;\r\n\t\t\t\tlastTabIdForTitle = myTabId;\r\n\t\t\t\tconst title = computeTabTitle();\r\n\t\t\t\tconst prev = this.bridgeSvc.activeMFEUrl();\r\n\t\t\t\tif (prev?.tabId === myTabId && prev?.url === url && prev?.title === title) return;\r\n\t\t\t\tthis.bridgeSvc.activeMFEUrl.set({ tabId: myTabId, url, title });\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\t// Component cevap gelince `breadcrumbService.set('meterNo', '12345')` keyValues'ı\r\n\t\t// günceller; effect ile yakalayıp tab title'ı yeniden hesaplarız → \"12345 - Sayaç\r\n\t\t// Detayı\" gibi dinamik sonuçlar tab adına yansır.\r\n\t\teffect(\r\n\t\t\t() => {\r\n\t\t\t\tbreadcrumbService.keyValues();\r\n\t\t\t\tif (!lastUrl || !lastTabIdForTitle) return;\r\n\t\t\t\tconst title = computeTabTitle();\r\n\t\t\t\tconst prev = this.bridgeSvc.activeMFEUrl();\r\n\t\t\t\tif (prev?.tabId === lastTabIdForTitle && prev?.url === lastUrl && prev?.title === title) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tthis.bridgeSvc.activeMFEUrl.set({ tabId: lastTabIdForTitle, url: lastUrl, title });\r\n\t\t\t},\r\n\t\t\t{ allowSignalWrites: true }\r\n\t\t);\r\n\r\n\t\tconst mfePrefix = `/${appName}`;\r\n\r\n\t\tthis.bridgeSvc.hostRouter!.events.pipe(takeUntilDestroyed()).subscribe((event: RouterEvent) => {\r\n\t\t\tif (event.type === EventType.NavigationEnd) {\r\n\t\t\t\tconst target = event.urlAfterRedirects ?? event.url;\r\n\t\t\t\tif (target !== mfePrefix && !target.startsWith(`${mfePrefix}/`)) return;\r\n\t\t\t\t// **Tab izolasyonu filter**: navigation'ın hedef tab'ı bu instance mı?\r\n\t\t\t\t// `IsolatedLocationStrategy` sayesinde host'a sadece tab tıklamaları\r\n\t\t\t\t// (`tabState({_tab})` ile) gelir — `history.state._tab` her zaman dolu.\r\n\t\t\t\tconst myTabId = readMyTabId();\r\n\t\t\t\tif (myTabId) {\r\n\t\t\t\t\tconst navTabId = (window.history.state as Record<string, unknown> | null)?.['_tab'];\r\n\t\t\t\t\tif (navTabId !== myTabId) return;\r\n\t\t\t\t}\r\n\t\t\t\t// `lastNavigated`/`router.url===target` early-return YOK: izole Router'da (her tab\r\n\t\t\t\t// kendi Router'ı) bir tab'a geri dönüldüğünde MFE Router zaten hedef URL'dedir;\r\n\t\t\t\t// navigate atlanırsa NavigationEnd fire etmez → `BreadcrumbPublisherService` yeniden\r\n\t\t\t\t// yayın yapmaz ve app.layout tab geçişinde breadcrumb'ı `set([])` ile temizlediği için\r\n\t\t\t\t// breadcrumb boş kalır. `onSameUrlNavigation:'reload'` aynı URL'e navigate'i\r\n\t\t\t\t// NavigationEnd ile garanti eder → breadcrumb + tab navLink yeniden yayınlanır.\r\n\t\t\t\tconsole.log(`[MFE:${appName}] tab=\"${myTabId || '(pending)'}\" host NavigationEnd → navigate:`, target);\r\n\t\t\t\tsafeNavigate(this.router, target);\r\n\t\t\t} else if (event.type === EventType.NavigationCancel) {\r\n\t\t\t\tconsole.warn(`[MFE:${appName}] host NavigationCancel:`, event.url, 'reason:', event.reason);\r\n\t\t\t} else if (event.type === EventType.NavigationError) {\r\n\t\t\t\tconsole.error(`[MFE:${appName}] host NavigationError:`, event.url, 'err:', event.error);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tthis.bridgeSvc.activeMF.set(appName);\r\n\t\tconst lang: LanguageCode = (localStorage.getItem('lang') as LanguageCode) ?? LanguageCode.TR;\r\n\r\n\t\tthis.translocoService.setActiveLang(lang);\r\n\r\n\t\tthis.setLocale(lang);\r\n\t}\r\n\r\n\tsetLocale(lang: LanguageCode) {\r\n\t\tif (!lang?.length) return;\r\n\r\n\t\tif (lang === LanguageCode.TR) {\r\n\t\t\tthis.primeNgConfig.setTranslation(TR_TRANSLATIONS);\r\n\t\t}\r\n\t}\r\n}\r\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LocationStrategy, Location } from '@angular/common';
|
|
2
2
|
import { HttpClient } from '@angular/common/http';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { Injectable, APP_INITIALIZER, importProvidersFrom, ɵINJECTOR_SCOPE as _INJECTOR_SCOPE, ApplicationRef, createEnvironmentInjector, isDevMode, createComponent } from '@angular/core';
|
|
4
|
+
import { Injectable, APP_INITIALIZER, importProvidersFrom, ɵINJECTOR_SCOPE as _INJECTOR_SCOPE, ApplicationRef, inject, EnvironmentInjector, createEnvironmentInjector, isDevMode, createComponent } from '@angular/core';
|
|
5
5
|
import { createApplication } from '@angular/platform-browser';
|
|
6
6
|
import { provideRouter, withComponentInputBinding, withRouterConfig, RouteReuseStrategy, UrlSerializer, Router } from '@angular/router';
|
|
7
7
|
import { PrimeNGConfig, MessageService, ConfirmationService } from 'primeng/api';
|
|
@@ -17,7 +17,7 @@ import { provideHost } from 'aril/provider';
|
|
|
17
17
|
import { PubSubService } from 'aril/util/pub-sub';
|
|
18
18
|
|
|
19
19
|
const appComponentLoader = async () => {
|
|
20
|
-
const { AppComponent } = await import('./aril-boot-mfe-app.component-
|
|
20
|
+
const { AppComponent } = await import('./aril-boot-mfe-app.component-oxzMhRXe.mjs');
|
|
21
21
|
return AppComponent;
|
|
22
22
|
};
|
|
23
23
|
|
|
@@ -501,9 +501,41 @@ const boot = (_appName, _routes, _menuItems) => {
|
|
|
501
501
|
// detection almaz. AppComponent'i biz açıkça `sharedAppRef.attachView` ile bağladığımız için
|
|
502
502
|
// çalışır; ama `inject(ApplicationRef)` yapan üçüncü taraf kod (PrimeNG `DialogService` →
|
|
503
503
|
// `this.appRef.attachView`) child-local sahte appRef'i alıp dialog'u ona bağlıyordu → dialog
|
|
504
|
-
// yaratılıyor ama `*ngIf="visible"` hiç render edilmiyordu (boş açılıyordu).
|
|
505
|
-
//
|
|
506
|
-
|
|
504
|
+
// yaratılıyor ama `*ngIf="visible"` hiç render edilmiyordu (boş açılıyordu).
|
|
505
|
+
//
|
|
506
|
+
// Çözüm — `sharedAppRef`'i saran Proxy: TÜM üyeler (attachView/detachView/tick/components…)
|
|
507
|
+
// gerçek `sharedAppRef`'e delege olur (method'lar `target`'a bind'li → private field dahil
|
|
508
|
+
// doğru `this`), TEK fark `.injector` → bu tab'ın child injector'ı. Neden kritik: PrimeNG
|
|
509
|
+
// `DialogService` dialog'u `createComponent(..., { environmentInjector: this.appRef.injector })`
|
|
510
|
+
// ile yaratır. Düz `sharedAppRef` dönersek dialog içeriği shared ROOT'ta çözülür, sayfa ise
|
|
511
|
+
// child injector'da → `providedIn:'root'` her servis İKİ ayrı instance olur (split-brain) ve
|
|
512
|
+
// BehaviorSubject tabanlı sayfa↔dialog state senkronize OLMAZ (seçili kayıt dialog'da null).
|
|
513
|
+
// `.injector`'ı child'a yönlendirince dialog içeriği sayfayla AYNI injector'da çözer → otomatik
|
|
514
|
+
// tek instance, TÜM (mevcut+gelecek) servisler için — servis listesi tutmaya gerek yok.
|
|
515
|
+
// `attachView` yine `sharedAppRef`'e gittiği için tek tick döngüsü/change detection korunur.
|
|
516
|
+
{
|
|
517
|
+
provide: ApplicationRef,
|
|
518
|
+
useFactory: () => {
|
|
519
|
+
const tabInjector = inject(EnvironmentInjector);
|
|
520
|
+
return new Proxy(sharedAppRef, {
|
|
521
|
+
get(target, prop) {
|
|
522
|
+
if (prop === 'injector')
|
|
523
|
+
return tabInjector;
|
|
524
|
+
// `ngOnDestroy`'u GİZLE (undefined döndür). Aksi halde `inject(ApplicationRef)`
|
|
525
|
+
// yapan tab child injector'ı (PrimeNG DialogService veya aşağıdaki dev guard)
|
|
526
|
+
// proxy'yi kendi `_ngOnDestroyHooks`'una kaydeder (R3Injector.hydrate →
|
|
527
|
+
// hasOnDestroy=true) ve tab kapanışında `childInjector.destroy()` →
|
|
528
|
+
// `sharedAppRef.ngOnDestroy()` → açık TÜM tab'ların view'larını destroy edip
|
|
529
|
+
// shared app'i öldürür. Shared app'in lifecycle'ı bootstrap'a aittir, tab'a değil
|
|
530
|
+
// (gerçek `sharedAppRef.ngOnDestroy` etkilenmez; yalnızca proxy üzerinden gizlenir).
|
|
531
|
+
if (prop === 'ngOnDestroy')
|
|
532
|
+
return undefined;
|
|
533
|
+
const value = Reflect.get(target, prop, target);
|
|
534
|
+
return typeof value === 'function' ? value.bind(target) : value;
|
|
535
|
+
}
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
},
|
|
507
539
|
// Tarama (log15) ile saptanan, child-local olunca bozulan ek `providedIn:'root'` servisleri:
|
|
508
540
|
// • PubSubService — MFE'nin `breadcrumbUpdated` event'i host `history.service`'e ulaşmalı;
|
|
509
541
|
// child-local olunca MFE↔host event köprüsü kopuyordu.
|
|
@@ -517,6 +549,10 @@ const boot = (_appName, _routes, _menuItems) => {
|
|
|
517
549
|
// görünmez. Shared instance ile tüm `<p-toast key="toast-root">` container'ları aynı kuyruğu dinler.
|
|
518
550
|
{ provide: MessageService, useFactory: () => sharedAppRef.injector.get(MessageService) },
|
|
519
551
|
{ provide: ConfirmationService, useFactory: () => sharedAppRef.injector.get(ConfirmationService) }
|
|
552
|
+
// SelectionGroupService bilinçli olarak BURADA YOK: tüm state'i (signal + loaded/loading +
|
|
553
|
+
// init flag'i) globalThis bridge'de yaşar; child-local instance'lar da aynı state'i alias'lar,
|
|
554
|
+
// bu yüzden instance sayısının önemi yoktur — forwarding yalnızca instance-local state'i olan
|
|
555
|
+
// servisler (MessageService vb.) için gereklidir.
|
|
520
556
|
];
|
|
521
557
|
const appComponentPromise = appComponentLoader();
|
|
522
558
|
class MFEAppElement extends HTMLElement {
|
|
@@ -556,6 +592,14 @@ const boot = (_appName, _routes, _menuItems) => {
|
|
|
556
592
|
console.error(`[boot:${_appName}] HİBRİT İZOLASYON BOZULDU: child Router shared root ile aynı instance! ` +
|
|
557
593
|
`ɵINJECTOR_SCOPE davranışı değişmiş olabilir (Angular upgrade?) — tab izolasyonu çalışmaz.`);
|
|
558
594
|
}
|
|
595
|
+
// [Dialog injector köprüsü guard — kalıcı] ApplicationRef proxy'sinin `.injector`'ı bu
|
|
596
|
+
// tab'ın child injector'ını göstermeli; aksi halde PrimeNG DialogService dialog içeriğini
|
|
597
|
+
// shared root'ta çözer → sayfa↔dialog `providedIn:'root'` split-brain geri döner. PrimeNG
|
|
598
|
+
// ya da Angular upgrade'i `appRef.injector` kullanımını değiştirirse burada yakalanır.
|
|
599
|
+
if (isDevMode() && this.childInjector.get(ApplicationRef).injector !== this.childInjector) {
|
|
600
|
+
console.error(`[boot:${_appName}] DIALOG INJECTOR KÖPRÜSÜ BOZULDU: ApplicationRef.injector tab child ` +
|
|
601
|
+
`injector'ı göstermiyor — dialog içeriği sayfadan farklı injector'da çözülür (split-brain).`);
|
|
602
|
+
}
|
|
559
603
|
// AppComponent'i child injector context'inde yarat → inject(Router)/LocationStrategy
|
|
560
604
|
// child-local; inject(MfeBridge)/HttpClient/Keycloak/TranslocoService vb. parent'tan
|
|
561
605
|
// paylaşımlı. `attachView` shared app'in change detection döngüsüne bağlar. (`bootstrap`
|
|
@@ -628,4 +672,4 @@ const boot = (_appName, _routes, _menuItems) => {
|
|
|
628
672
|
*/
|
|
629
673
|
|
|
630
674
|
export { appName as a, boot as b };
|
|
631
|
-
//# sourceMappingURL=aril-boot-mfe-aril-boot-mfe-
|
|
675
|
+
//# sourceMappingURL=aril-boot-mfe-aril-boot-mfe-CKOM61xb.mjs.map
|