aril 1.2.18 → 2.0.1-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/boot/bridge/src/mfe-bridge.d.ts +42 -2
  2. package/boot/config/apps/index.d.ts +7 -1
  3. package/boot/config/apps/src/custom-reuse-outlet.component.d.ts +37 -0
  4. package/boot/config/apps/src/custom-route-reuse-strategy.class.d.ts +156 -0
  5. package/boot/config/apps/src/nav-link-context-menu.service.d.ts +33 -0
  6. package/boot/config/apps/src/nav-link.directive.d.ts +29 -0
  7. package/boot/config/apps/src/nav.service.d.ts +198 -0
  8. package/boot/config/apps/src/route-close.service.d.ts +9 -0
  9. package/boot/config/apps/src/safe-navigate.d.ts +17 -0
  10. package/boot/config/apps/src/tab-aware-url-serializer.d.ts +22 -0
  11. package/boot/config/plugins/src/getNgZone.d.ts +9 -1
  12. package/boot/mfe/src/app.component.d.ts +15 -4
  13. package/boot/mfe/src/isolated-location-strategy.d.ts +57 -0
  14. package/esm2022/boot/bridge/src/mfe-bridge.mjs +36 -5
  15. package/esm2022/boot/config/api/src/api.service.mjs +12 -3
  16. package/esm2022/boot/config/apps/index.mjs +8 -2
  17. package/esm2022/boot/config/apps/src/apps.service.mjs +14 -6
  18. package/esm2022/boot/config/apps/src/custom-reuse-outlet.component.mjs +207 -0
  19. package/esm2022/boot/config/apps/src/custom-route-reuse-strategy.class.mjs +540 -0
  20. package/esm2022/boot/config/apps/src/nav-link-context-menu.service.mjs +105 -0
  21. package/esm2022/boot/config/apps/src/nav-link.directive.mjs +45 -0
  22. package/esm2022/boot/config/apps/src/nav.service.mjs +675 -0
  23. package/esm2022/boot/config/apps/src/route-close.service.mjs +19 -0
  24. package/esm2022/boot/config/apps/src/safe-navigate.mjs +50 -0
  25. package/esm2022/boot/config/apps/src/tab-aware-url-serializer.mjs +50 -0
  26. package/esm2022/boot/config/plugins/src/getNgZone.mjs +13 -5
  27. package/esm2022/boot/host/src/app.component.mjs +1 -2
  28. package/esm2022/boot/host/src/bootstrap.mjs +22 -7
  29. package/esm2022/boot/mfe/src/app.component.mjs +143 -39
  30. package/esm2022/boot/mfe/src/bootstrap.mjs +197 -20
  31. package/esm2022/boot/mfe/src/isolated-location-strategy.mjs +142 -0
  32. package/esm2022/keycloak/src/auth.interceptor.mjs +17 -2
  33. package/esm2022/provider/src/prodiveHost.mjs +3 -5
  34. package/esm2022/provider/src/prodiveHostRouter.mjs +88 -9
  35. package/esm2022/theme/layout/app/expandableMenu/expandable-menu.component.mjs +81 -19
  36. package/esm2022/theme/layout/app/favorite-pages/favorite-pages-sidebar.component.mjs +6 -4
  37. package/esm2022/theme/layout/app/general-search/general-search.component.mjs +4 -4
  38. package/esm2022/theme/layout/app/history/history-sidebar.component.mjs +6 -4
  39. package/esm2022/theme/layout/app/layout/app.layout.component.mjs +422 -20
  40. package/esm2022/theme/layout/app/layout/mfe.layout.component.mjs +22 -35
  41. package/esm2022/theme/layout/app/site-map/site-map-sidebar.component.mjs +6 -4
  42. package/esm2022/theme/layout/app/static-sidebar/static-sidebar.component.mjs +85 -27
  43. package/esm2022/theme/layout/app/topbar/app.topbar.component.mjs +3 -3
  44. package/esm2022/theme/layout/service/breadcrumb-publisher.service.mjs +86 -0
  45. package/esm2022/theme/layout/service/tab-session.service.mjs +126 -0
  46. package/esm2022/ui-business/ref-value/src/ref-value.component.mjs +15 -7
  47. package/esm2022/util/sync-active-tab-route/src/sync-active-tab-route.directive.mjs +29 -9
  48. package/fesm2022/aril-app.component-s14ruALV.mjs +183 -0
  49. package/fesm2022/aril-app.component-s14ruALV.mjs.map +1 -0
  50. package/fesm2022/aril-boot-bridge.mjs +35 -4
  51. package/fesm2022/aril-boot-bridge.mjs.map +1 -1
  52. package/fesm2022/aril-boot-config-api.mjs +11 -2
  53. package/fesm2022/aril-boot-config-api.mjs.map +1 -1
  54. package/fesm2022/aril-boot-config-apps.mjs +1678 -10
  55. package/fesm2022/aril-boot-config-apps.mjs.map +1 -1
  56. package/fesm2022/aril-boot-config-plugins.mjs +12 -4
  57. package/fesm2022/aril-boot-config-plugins.mjs.map +1 -1
  58. package/fesm2022/aril-boot-host.mjs +21 -7
  59. package/fesm2022/aril-boot-host.mjs.map +1 -1
  60. package/fesm2022/aril-boot-mfe-app.component-a34GeuUv.mjs +183 -0
  61. package/fesm2022/aril-boot-mfe-app.component-a34GeuUv.mjs.map +1 -0
  62. package/fesm2022/aril-boot-mfe-aril-boot-mfe-KFO_X7yR.mjs +631 -0
  63. package/fesm2022/aril-boot-mfe-aril-boot-mfe-KFO_X7yR.mjs.map +1 -0
  64. package/fesm2022/aril-boot-mfe.mjs +5 -3
  65. package/fesm2022/aril-boot-mfe.mjs.map +1 -1
  66. package/fesm2022/aril-keycloak.mjs +16 -1
  67. package/fesm2022/aril-keycloak.mjs.map +1 -1
  68. package/fesm2022/aril-provider.mjs +90 -12
  69. package/fesm2022/aril-provider.mjs.map +1 -1
  70. package/fesm2022/aril-theme-layout.mjs +2628 -2017
  71. package/fesm2022/aril-theme-layout.mjs.map +1 -1
  72. package/fesm2022/aril-ui-business-ref-value.mjs +14 -6
  73. package/fesm2022/aril-ui-business-ref-value.mjs.map +1 -1
  74. package/fesm2022/aril-util-sync-active-tab-route.mjs +28 -8
  75. package/fesm2022/aril-util-sync-active-tab-route.mjs.map +1 -1
  76. package/fesm2022/aril.mjs +354 -25
  77. package/fesm2022/aril.mjs.map +1 -1
  78. package/keycloak/src/auth.interceptor.d.ts +7 -0
  79. package/package.json +222 -222
  80. package/provider/src/prodiveHost.d.ts +1 -0
  81. package/theme/layout/app/expandableMenu/expandable-menu.component.d.ts +21 -4
  82. package/theme/layout/app/expandableMenu/expandable-menu.component.html +19 -5
  83. package/theme/layout/app/expandableMenu/expandable-menu.component.ts +69 -9
  84. package/theme/layout/app/favorite-pages/favorite-pages-sidebar.component.html +1 -0
  85. package/theme/layout/app/favorite-pages/favorite-pages-sidebar.component.ts +3 -1
  86. package/theme/layout/app/general-search/general-search.component.html +2 -1
  87. package/theme/layout/app/general-search/general-search.component.ts +2 -2
  88. package/theme/layout/app/history/history-sidebar.component.html +3 -1
  89. package/theme/layout/app/history/history-sidebar.component.ts +3 -1
  90. package/theme/layout/app/layout/app.layout.component.d.ts +105 -5
  91. package/theme/layout/app/layout/app.layout.component.html +102 -1
  92. package/theme/layout/app/layout/app.layout.component.scss +372 -0
  93. package/theme/layout/app/layout/app.layout.component.ts +452 -13
  94. package/theme/layout/app/layout/mfe.layout.component.d.ts +1 -5
  95. package/theme/layout/app/layout/mfe.layout.component.ts +12 -38
  96. package/theme/layout/app/site-map/site-map-sidebar.component.html +1 -0
  97. package/theme/layout/app/site-map/site-map-sidebar.component.ts +3 -1
  98. package/theme/layout/app/static-sidebar/static-sidebar.component.d.ts +26 -5
  99. package/theme/layout/app/static-sidebar/static-sidebar.component.html +11 -5
  100. package/theme/layout/app/static-sidebar/static-sidebar.component.ts +68 -13
  101. package/theme/layout/app/topbar/app.topbar.component.html +0 -1
  102. package/theme/layout/app/topbar/app.topbar.component.scss +1 -1
  103. package/theme/layout/service/breadcrumb-publisher.service.d.ts +24 -0
  104. package/theme/layout/service/breadcrumb-publisher.service.ts +95 -0
  105. package/theme/layout/service/tab-session.service.d.ts +52 -0
  106. package/theme/layout/service/tab-session.service.ts +138 -0
  107. package/theme/styles/layout/_breadcrumb.scss +95 -0
  108. package/theme/styles/layout/_content.scss +2 -2
  109. package/ui-business/ref-value/src/ref-value.component.d.ts +4 -2
  110. package/util/sync-active-tab-route/src/sync-active-tab-route.directive.d.ts +15 -2
  111. package/boot/config/apps/src/reuse-strategy.d.ts +0 -4
  112. package/esm2022/boot/config/apps/src/reuse-strategy.mjs +0 -9
  113. package/esm2022/theme/layout/app/breadcrumb/app.breadcrumb.component.mjs +0 -107
  114. package/fesm2022/aril-app.component-wxP3y8dg.mjs +0 -81
  115. package/fesm2022/aril-app.component-wxP3y8dg.mjs.map +0 -1
  116. package/fesm2022/aril-boot-mfe-app.component-7IjAmjz0.mjs +0 -80
  117. package/fesm2022/aril-boot-mfe-app.component-7IjAmjz0.mjs.map +0 -1
  118. package/fesm2022/aril-boot-mfe-aril-boot-mfe-KXDpUyv7.mjs +0 -315
  119. package/fesm2022/aril-boot-mfe-aril-boot-mfe-KXDpUyv7.mjs.map +0 -1
  120. package/theme/layout/app/breadcrumb/app.breadcrumb.component.d.ts +0 -25
  121. package/theme/layout/app/breadcrumb/app.breadcrumb.component.html +0 -8
  122. package/theme/layout/app/breadcrumb/app.breadcrumb.component.ts +0 -127
@@ -0,0 +1,631 @@
1
+ import { LocationStrategy, Location } from '@angular/common';
2
+ import { HttpClient } from '@angular/common/http';
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';
5
+ import { createApplication } from '@angular/platform-browser';
6
+ import { provideRouter, withComponentInputBinding, withRouterConfig, RouteReuseStrategy, UrlSerializer, Router } from '@angular/router';
7
+ import { PrimeNGConfig, MessageService, ConfirmationService } from 'primeng/api';
8
+ import { TranslocoService } from '@ngneat/transloco';
9
+ import { KeycloakService } from 'keycloak-angular';
10
+ import { MonacoEditorModule, NGX_MONACO_EDITOR_CONFIG } from 'ngx-monaco-editor-v2';
11
+ import { createBaseAppConfig } from 'aril/boot/base';
12
+ import { setApiConfigOnMFEMode } from 'aril/boot/config/api';
13
+ import { CustomRouteReuseStrategy, TabAwareUrlSerializer } from 'aril/boot/config/apps';
14
+ import { getNgZone, loadPlugins } from 'aril/boot/config/plugins';
15
+ import { i18nFolderName } from 'aril/i18n';
16
+ import { provideHost } from 'aril/provider';
17
+ import { PubSubService } from 'aril/util/pub-sub';
18
+
19
+ const appComponentLoader = async () => {
20
+ const { AppComponent } = await import('./aril-boot-mfe-app.component-a34GeuUv.mjs');
21
+ return AppComponent;
22
+ };
23
+
24
+ /**
25
+ * Host modda her MFE Application'ı için kullanılan custom `LocationStrategy`. Browser
26
+ * URL'ine (`window.location.hash`) HİÇ YAZMAZ; tüm path/state internal alanlarda tutulur.
27
+ *
28
+ * Neden? Host modda host Router yegane URL kontrolcüsüdür. Eğer MFE Router da
29
+ * `HashLocationStrategy` kullansaydı, MFE içindeki bir `routerLink` tıklaması browser hash'ını
30
+ * değiştirir → `HashLocationStrategy` host Router'ı OTOMATİK tetikler → host Router'a
31
+ * tabsız (state'siz) navigation gelir → Strategy yanlış componentRef yaratır, tab
32
+ * izolasyonu bozulur. Bu otomatik sync'i kırmak için MFE Router'ın LocationStrategy'sini
33
+ * isolate ediyoruz: MFE içi navigation MFE Router'ın internal state'inde kalır, browser'a
34
+ * sızmaz, host'a istemsiz event göndermez.
35
+ *
36
+ * ## Tab içi history stack
37
+ * Browser back/forward butonu yerine MFE içinde **tab-içi history stack** çalışır:
38
+ * `pushState` her yeni navigation'da `backStack`'e mevcut konumu iter, `forwardStack`'i
39
+ * temizler; `back()` ve `forward()` stack'ler arasında değiş tokuş yapıp `popstate` event'i
40
+ * emit eder — Angular `Location` service bunu Router'a iletir, Router popstate-driven
41
+ * navigation cycle başlatır. Sonuçta kullanıcı **detay → liste** gibi MFE içi geri dönüşleri
42
+ * browser back butonuyla yapabilir, ama bu navigation **host Router'a yansımaz** → tab
43
+ * izolasyonu korunur, "geri" başka tab'a atlatmaz.
44
+ */
45
+ class IsolatedLocationStrategy extends LocationStrategy {
46
+ /**
47
+ * Stack boyutu üst limiti — browser default'una (50 entry) yakın. Aşırı uzun
48
+ * session'larda memory'i sınırlı tutar; sınır aşıldığında en eski entry düşürülür.
49
+ */
50
+ static { this.MAX_STACK_SIZE = 50; }
51
+ constructor() {
52
+ super();
53
+ this.internalPath = '/';
54
+ this.internalState = null;
55
+ /** Geri gidilebilecek path/state çiftleri (LIFO). */
56
+ this.backStack = [];
57
+ /** İleri gidilebilecek path/state çiftleri (`back()` ile pop edilen entry'ler). */
58
+ this.forwardStack = [];
59
+ this.popStateHandlers = [];
60
+ /**
61
+ * `back/forward` sonrası Router'ın navigation cycle'ı sırasında çağrılabilen
62
+ * `pushState`'i `backStack`'e tekrar itmemek için flag. `replaceState` zaten stack'i
63
+ * değiştirmiyor — bu flag yalnızca pushState yolunu koruyor.
64
+ */
65
+ this.isNavigatingViaHistory = false;
66
+ console.log('[IsolatedLocationStrategy] CONSTRUCTED — host modda MFE Router için aktif');
67
+ }
68
+ path(_includeHash) {
69
+ return this.internalPath;
70
+ }
71
+ prepareExternalUrl(internal) {
72
+ // Host `HashLocationStrategy` (withHashLocation) kullanıyor → MFE routerLink'lerinin
73
+ // ürettiği `<a href>` (hover/kopyalama/orta-tık/yeni sekme) host ile uyumlu `#/...`
74
+ // formatında olmalı. Sol-tık navigation'ı zaten host Router proxy üzerinden gider
75
+ // (href kullanılmaz); bu override yalnız görünen/kopyalanan URL'i düzeltir.
76
+ return internal.length > 0 ? '#' + internal : internal;
77
+ }
78
+ pushState(state, _title, url, queryParams) {
79
+ const fullPath = url + (queryParams ? `?${queryParams}` : '');
80
+ console.log(`[IsolatedLocationStrategy] pushState url="${url}" qs="${queryParams}" viaHistory=${this.isNavigatingViaHistory}`);
81
+ if (!this.isNavigatingViaHistory) {
82
+ // Yeni navigation → mevcut konumu backStack'e it, forwardStack'i temizle
83
+ // (browser semantiği: yeni sayfaya gidince forward history düşer).
84
+ if (this.internalPath !== fullPath) {
85
+ this.backStack.push({ path: this.internalPath, state: this.internalState });
86
+ if (this.backStack.length > IsolatedLocationStrategy.MAX_STACK_SIZE) {
87
+ this.backStack.shift();
88
+ }
89
+ this.forwardStack = [];
90
+ }
91
+ }
92
+ this.internalPath = fullPath;
93
+ this.internalState = state;
94
+ }
95
+ replaceState(state, _title, url, queryParams) {
96
+ console.log(`[IsolatedLocationStrategy] replaceState url="${url}" qs="${queryParams}"`);
97
+ this.internalPath = url + (queryParams ? `?${queryParams}` : '');
98
+ this.internalState = state;
99
+ }
100
+ back() {
101
+ const prev = this.backStack.pop();
102
+ if (!prev)
103
+ return;
104
+ this.forwardStack.push({ path: this.internalPath, state: this.internalState });
105
+ this.internalPath = prev.path;
106
+ this.internalState = prev.state;
107
+ this.emitPopState();
108
+ }
109
+ forward() {
110
+ const next = this.forwardStack.pop();
111
+ if (!next)
112
+ return;
113
+ this.backStack.push({ path: this.internalPath, state: this.internalState });
114
+ this.internalPath = next.path;
115
+ this.internalState = next.state;
116
+ this.emitPopState();
117
+ }
118
+ historyGo(relativePosition) {
119
+ if (relativePosition < 0) {
120
+ const steps = -relativePosition;
121
+ for (let i = 0; i < steps && this.backStack.length; i++)
122
+ this.back();
123
+ }
124
+ else if (relativePosition > 0) {
125
+ for (let i = 0; i < relativePosition && this.forwardStack.length; i++)
126
+ this.forward();
127
+ }
128
+ }
129
+ onPopState(fn) {
130
+ this.popStateHandlers.push(fn);
131
+ }
132
+ emitPopState() {
133
+ this.isNavigatingViaHistory = true;
134
+ try {
135
+ const event = new PopStateEvent('popstate', { state: this.internalState });
136
+ for (const fn of this.popStateHandlers)
137
+ fn(event);
138
+ }
139
+ finally {
140
+ // Router'ın navigation cycle'ı async — popstate handler'ı navigation tetikledikten
141
+ // sonra cycle bittiğinde pushState/replaceState çağrılabilir. Microtask sınırı
142
+ // sync cycle'ı kapsar; daha güvenli istersek `queueMicrotask` yerine `setTimeout(0)`
143
+ // tercih edilebilir ama bu durumda araya gerçek user navigation girebilir. Microtask
144
+ // pratikte yeterli: Router popstate cycle'ında pushState değil replaceState çağırır.
145
+ queueMicrotask(() => {
146
+ this.isNavigatingViaHistory = false;
147
+ });
148
+ }
149
+ }
150
+ getBaseHref() {
151
+ return '/';
152
+ }
153
+ getState() {
154
+ return this.internalState;
155
+ }
156
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: IsolatedLocationStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
157
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: IsolatedLocationStrategy }); }
158
+ }
159
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: IsolatedLocationStrategy, decorators: [{
160
+ type: Injectable
161
+ }], ctorParameters: () => [] });
162
+
163
+ const monacoConfig = {
164
+ baseUrl: 'assets',
165
+ defaultOptions: { scrollBeyondLastLine: false },
166
+ onMonacoLoad: () => {
167
+ // JSON düzenleyici ayarları
168
+ if (monaco && monaco.languages && monaco.languages.json) {
169
+ monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
170
+ validate: true,
171
+ allowComments: false,
172
+ schemas: []
173
+ });
174
+ }
175
+ // JavaScript/TypeScript düzenleyici ayarları
176
+ if (monaco && monaco.languages && monaco.languages.typescript) {
177
+ monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
178
+ target: monaco.languages.typescript.ScriptTarget.ES2016,
179
+ allowNonTsExtensions: true,
180
+ moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
181
+ module: monaco.languages.typescript.ModuleKind.CommonJS,
182
+ noEmit: true,
183
+ typeRoots: ['node_modules/@types']
184
+ });
185
+ // TypeScript düzenleyici ayarları
186
+ monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
187
+ target: monaco.languages.typescript.ScriptTarget.ES2016,
188
+ allowNonTsExtensions: true,
189
+ moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
190
+ module: monaco.languages.typescript.ModuleKind.CommonJS,
191
+ noEmit: true,
192
+ typeRoots: ['node_modules/@types']
193
+ });
194
+ }
195
+ // HTML, XML ve diğer markup dilleri için ayarlar
196
+ if (monaco && monaco.languages && monaco.languages.html) {
197
+ monaco.languages.html.htmlDefaults.setOptions({
198
+ format: {
199
+ tabSize: 2,
200
+ insertSpaces: true
201
+ },
202
+ suggest: {
203
+ html5: true
204
+ }
205
+ });
206
+ }
207
+ // Python için syntax highlighting ve özel formatlamalar
208
+ if (monaco && monaco.languages) {
209
+ monaco.languages.registerDocumentFormattingEditProvider('python', {
210
+ provideDocumentFormattingEdits: function (model) {
211
+ const text = model.getValue();
212
+ return [
213
+ {
214
+ range: model.getFullModelRange(),
215
+ text: text
216
+ }
217
+ ];
218
+ }
219
+ });
220
+ // Python için özel linting kuralları
221
+ monaco.languages.registerCompletionItemProvider('python', {
222
+ provideCompletionItems: function (model, position) {
223
+ const suggestions = [
224
+ {
225
+ label: 'def',
226
+ kind: monaco.languages.CompletionItemKind.Keyword,
227
+ insertText: 'def ${1:function_name}(${2:parameters}):\n\t${3:pass}',
228
+ insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
229
+ documentation: 'Fonksiyon tanımlama'
230
+ },
231
+ {
232
+ label: 'class',
233
+ kind: monaco.languages.CompletionItemKind.Keyword,
234
+ insertText: 'class ${1:ClassName}:\n\tdef __init__(self, ${2:parameters}):\n\t\t${3:pass}',
235
+ insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
236
+ documentation: 'Sınıf tanımlama'
237
+ },
238
+ {
239
+ label: 'if',
240
+ kind: monaco.languages.CompletionItemKind.Keyword,
241
+ insertText: 'if ${1:condition}:\n\t${2:pass}',
242
+ insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
243
+ documentation: 'If bloğu'
244
+ },
245
+ {
246
+ label: 'for',
247
+ kind: monaco.languages.CompletionItemKind.Keyword,
248
+ insertText: 'for ${1:item} in ${2:iterable}:\n\t${3:pass}',
249
+ insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
250
+ documentation: 'For döngüsü'
251
+ }
252
+ ];
253
+ return { suggestions: suggestions };
254
+ }
255
+ });
256
+ }
257
+ // Lua için özel ayarlar
258
+ if (monaco && monaco.languages) {
259
+ monaco.languages.registerDocumentFormattingEditProvider('lua', {
260
+ provideDocumentFormattingEdits: function (model) {
261
+ const text = model.getValue();
262
+ return [
263
+ {
264
+ range: model.getFullModelRange(),
265
+ text: text
266
+ }
267
+ ];
268
+ }
269
+ });
270
+ monaco.languages.registerCompletionItemProvider('lua', {
271
+ provideCompletionItems: function (model, position) {
272
+ const suggestions = [
273
+ {
274
+ label: 'function',
275
+ kind: monaco.languages.CompletionItemKind.Keyword,
276
+ insertText: 'function ${1:name}(${2:params})\n\t${3:-- body}\nend',
277
+ insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
278
+ documentation: 'Fonksiyon tanımlama'
279
+ },
280
+ {
281
+ label: 'if',
282
+ kind: monaco.languages.CompletionItemKind.Keyword,
283
+ insertText: 'if ${1:condition} then\n\t${2:-- body}\nend',
284
+ insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
285
+ documentation: 'If bloğu'
286
+ },
287
+ {
288
+ label: 'for',
289
+ kind: monaco.languages.CompletionItemKind.Keyword,
290
+ insertText: 'for ${1:i}=${2:1},${3:10} do\n\t${4:-- body}\nend',
291
+ insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
292
+ documentation: 'For döngüsü'
293
+ }
294
+ ];
295
+ return { suggestions: suggestions };
296
+ }
297
+ });
298
+ }
299
+ // Java için özel ayarlar
300
+ if (monaco && monaco.languages) {
301
+ monaco.languages.registerDocumentFormattingEditProvider('java', {
302
+ provideDocumentFormattingEdits: function (model) {
303
+ const text = model.getValue();
304
+ // Java formatlaması
305
+ return [
306
+ {
307
+ range: model.getFullModelRange(),
308
+ text: text // Formatlanmış metin
309
+ }
310
+ ];
311
+ }
312
+ });
313
+ // Java için özel öneriler
314
+ monaco.languages.registerCompletionItemProvider('java', {
315
+ provideCompletionItems: function (model, position) {
316
+ const suggestions = [
317
+ {
318
+ label: 'class',
319
+ kind: monaco.languages.CompletionItemKind.Keyword,
320
+ insertText: 'public class ${1:ClassName} {\n\t${2}\n}',
321
+ insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
322
+ documentation: 'Sınıf tanımlama'
323
+ },
324
+ {
325
+ label: 'main',
326
+ kind: monaco.languages.CompletionItemKind.Snippet,
327
+ insertText: 'public static void main(String[] args) {\n\t${1}\n}',
328
+ insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
329
+ documentation: 'Main metodu'
330
+ },
331
+ {
332
+ label: 'sout',
333
+ kind: monaco.languages.CompletionItemKind.Snippet,
334
+ insertText: 'System.out.println(${1});',
335
+ insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
336
+ documentation: 'Konsola yazdırma'
337
+ }
338
+ ];
339
+ return { suggestions: suggestions };
340
+ }
341
+ });
342
+ }
343
+ // HTML için özel ayarlar
344
+ if (monaco && monaco.languages) {
345
+ monaco.languages.registerCompletionItemProvider('html', {
346
+ provideCompletionItems: function (model, position) {
347
+ const suggestions = [
348
+ {
349
+ label: 'html5',
350
+ kind: monaco.languages.CompletionItemKind.Snippet,
351
+ insertText: '<!DOCTYPE html>\n<html lang="en">\n<head>\n\t<meta charset="UTF-8">\n\t<meta name="viewport" content="width=device-width, initial-scale=1.0">\n\t<title>${1:Document}</title>\n</head>\n<body>\n\t${2}\n</body>\n</html>',
352
+ insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
353
+ documentation: 'HTML5 taslağı'
354
+ },
355
+ {
356
+ label: 'div',
357
+ kind: monaco.languages.CompletionItemKind.Snippet,
358
+ insertText: '<div class="${1:className}">\n\t${2}\n</div>',
359
+ insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
360
+ documentation: 'Div elementi'
361
+ }
362
+ ];
363
+ return { suggestions: suggestions };
364
+ }
365
+ });
366
+ }
367
+ // XML için özel ayarlar
368
+ if (monaco && monaco.languages) {
369
+ monaco.languages.registerCompletionItemProvider('xml', {
370
+ provideCompletionItems: function (model, position) {
371
+ const suggestions = [
372
+ {
373
+ label: 'xml',
374
+ kind: monaco.languages.CompletionItemKind.Snippet,
375
+ insertText: '<?xml version="1.0" encoding="UTF-8"?>\n<${1:root}>\n\t${2}\n</${1:root}>',
376
+ insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
377
+ documentation: 'XML taslağı'
378
+ }
379
+ ];
380
+ return { suggestions: suggestions };
381
+ }
382
+ });
383
+ }
384
+ // JSON için özel ayarlar ve şema doğrulama
385
+ if (monaco && monaco.languages && monaco.languages.json) {
386
+ monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
387
+ validate: true,
388
+ allowComments: false,
389
+ schemas: [
390
+ {
391
+ uri: 'http://myserver/schema/package.schema.json',
392
+ fileMatch: ['package.json'],
393
+ schema: {
394
+ type: 'object',
395
+ properties: {
396
+ name: { type: 'string' },
397
+ version: { type: 'string' },
398
+ dependencies: {
399
+ type: 'object'
400
+ }
401
+ }
402
+ }
403
+ }
404
+ ]
405
+ });
406
+ }
407
+ }
408
+ };
409
+
410
+ var appName;
411
+ var menuItems = [];
412
+ /**
413
+ * `boot` çağrılarının idempotent kalmasını sağlayan sync guard. Aynı remote için
414
+ * birden fazla paralel `boot('wdm', ...)` çağrısı geldiğinde, ilk `customElements.define`
415
+ * tamamlanmadan ikinci çağrı `customElements.get` guard'ını geçiyordu → her ikisi de
416
+ * define etmeye çalışıp `NotSupportedError: the name "app-wdm" has already been used`
417
+ * hatası fırlatılıyordu. Set ile sync mark ederek tek bir define cycle'ı garanti ediyoruz.
418
+ */
419
+ const bootedApps = new Set();
420
+ const boot = (_appName, _routes, _menuItems) => {
421
+ if (bootedApps.has(_appName) || customElements.get(`app-${_appName}`))
422
+ return;
423
+ bootedApps.add(_appName);
424
+ appName = _appName;
425
+ menuItems = _menuItems;
426
+ /**
427
+ * **Paylaşılan base config** — remote başına TEK `createApplication`. Ağır servisler
428
+ * (HttpClient + interceptor chain, Keycloak, i18n/Transloco, Monaco, animations) burada
429
+ * yaşar; `providedIn` taşımayan explicit provider oldukları için tüm tab'ların child
430
+ * injector'larından parent olarak paylaşılır → RAM lineer büyümez. Router/Location/
431
+ * ReuseStrategy/UrlSerializer burada YOK; onlar tab başına izole child injector'da verilir.
432
+ */
433
+ const sharedBaseConfig = {
434
+ providers: [
435
+ createBaseAppConfig({ i18nFolder: _appName }),
436
+ provideHost(_appName),
437
+ getNgZone(),
438
+ {
439
+ provide: APP_INITIALIZER,
440
+ useFactory: (httpClient, keycloak, folderName) => {
441
+ const runApiInit = setApiConfigOnMFEMode(httpClient, keycloak, folderName);
442
+ const runLoadPlugins = loadPlugins();
443
+ return async () => {
444
+ await runApiInit();
445
+ runLoadPlugins();
446
+ };
447
+ },
448
+ multi: true,
449
+ deps: [HttpClient, KeycloakService, i18nFolderName]
450
+ },
451
+ importProvidersFrom(MonacoEditorModule.forRoot()),
452
+ { provide: NGX_MONACO_EDITOR_CONFIG, useValue: monacoConfig }
453
+ ]
454
+ };
455
+ /**
456
+ * Remote başına TEK paylaşılan `ApplicationRef` — closure-scope. İlk `<app-${appName}>`
457
+ * element'i `createApplication(sharedBaseConfig)` çağırır, sonraki tüm element'ler aynı
458
+ * promise'ı bekler (duplicate Application yaratımı imkânsız). Her element kendi child
459
+ * injector + `createComponent` ile kendi `AppComponent` view'ını yaratıp shared app'e
460
+ * `attachView` ile bağlar. Shared app uzun ömürlüdür (tab'lar kapansa da destroy edilmez).
461
+ *
462
+ * `childProviders`'taki `TranslocoService` factory'si bu referansı kullandığı için
463
+ * `childProviders`'tan ÖNCE tanımlanır (forward TDZ'yi önler).
464
+ */
465
+ let sharedAppRef = null;
466
+ let sharedAppPromise = null;
467
+ /**
468
+ * **Tab başına izole Router stack** — her `<app-${appName}>` kendi child
469
+ * `EnvironmentInjector`'ında bunları alır. `ɵINJECTOR_SCOPE: 'root'` child'ı 'root'
470
+ * scope yapar (Angular `R3Injector` ctor: `scopes.add('root')`); böylece `provideRouter`'ın
471
+ * inject ettiği `providedIn:'root'` Router servisleri — `Router`, `ChildrenOutletContexts`,
472
+ * `Location`, `NavigationTransitions` vb. — child-LOCAL üretilir. Sonuç: her tab kendi
473
+ * Router + kendi `RouterOutlet` context'ine sahip olur → **1 Router : 1 outlet**.
474
+ *
475
+ * Neden gerekli: paylaşılan tek Application'da N `<router-outlet>` aynı tek
476
+ * `ChildrenOutletContexts`'e "primary" diye kaydolup birbirini eziyordu (`contexts.set`
477
+ * overwrite) → tab geçişi sonrası aynı tab içi navigasyon (list→detail) yanlış outlet'e
478
+ * render oluyordu. Child-injector izolasyonu bunu kökten çözer.
479
+ *
480
+ * **TranslocoService istisnası**: `'root'` scope onu da child-local yapardı; ama global
481
+ * (scope'suz) çeviriler shared app'in init akışında yüklendiğinden — `createComponent`
482
+ * `APP_INITIALIZER` çalıştırmaz — child-local service'in global cache'i boş kalıp ham key
483
+ * gösteriyordu. Tab başına ayrı dil senaryosu yok; service'i shared app'ten paylaştırıyoruz
484
+ * (global çeviri tek yerde yüklenir, tek translation cache → ek RAM kazancı). Scope çevirileri
485
+ * (`providei18nScope`) component-level sağlandığı için paylaşılan service'le de çalışır.
486
+ *
487
+ * NOT: `ɵINJECTOR_SCOPE` Angular private API'sidir; minor sürüm yükseltmelerinde davranışı
488
+ * doğrulanmalı (aşağıdaki POC izolasyon log'u bunun için bırakıldı).
489
+ */
490
+ const childProviders = [
491
+ { provide: _INJECTOR_SCOPE, useValue: 'root' },
492
+ provideRouter(_routes, withComponentInputBinding(), withRouterConfig({ onSameUrlNavigation: 'reload' })),
493
+ { provide: LocationStrategy, useClass: IsolatedLocationStrategy },
494
+ { provide: Location, useClass: Location },
495
+ { provide: RouteReuseStrategy, useExisting: CustomRouteReuseStrategy },
496
+ { provide: UrlSerializer, useExisting: TabAwareUrlSerializer },
497
+ { provide: TranslocoService, useFactory: () => sharedAppRef.injector.get(TranslocoService) },
498
+ // `ɵINJECTOR_SCOPE:'root'` yan etkisi: `ApplicationRef` de `providedIn:'root'` olduğu için
499
+ // child injector'da child-LOKAL (sahte) bir instance üretilirdi — bu instance NgZone'un
500
+ // tick döngüsüne bağlı DEĞİLDİR. Sonuç: bu appRef'e `attachView` edilen view'lar hiç change
501
+ // detection almaz. AppComponent'i biz açıkça `sharedAppRef.attachView` ile bağladığımız için
502
+ // çalışır; ama `inject(ApplicationRef)` yapan üçüncü taraf kod (PrimeNG `DialogService` →
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). Gerçek (tek,
505
+ // tick alan) `sharedAppRef`'e sabitliyoruz.
506
+ { provide: ApplicationRef, useFactory: () => sharedAppRef },
507
+ // Tarama (log15) ile saptanan, child-local olunca bozulan ek `providedIn:'root'` servisleri:
508
+ // • PubSubService — MFE'nin `breadcrumbUpdated` event'i host `history.service`'e ulaşmalı;
509
+ // child-local olunca MFE↔host event köprüsü kopuyordu.
510
+ // • PrimeNGConfig — dinamik dialog'lar shared root context'inde yaratıldığı için PrimeNG
511
+ // çevirileri (calendar/paginator vb.) ve `setTranslation` shared instance'tan okunmalı.
512
+ // (BreadcrumbService bilinçli olarak child-local bırakıldı: her tab kendi breadcrumb'ı.)
513
+ { provide: PubSubService, useFactory: () => sharedAppRef.injector.get(PubSubService) },
514
+ { provide: PrimeNGConfig, useFactory: () => sharedAppRef.injector.get(PrimeNGConfig) },
515
+ // Toast/confirm GLOBAL: tek shared MessageService/ConfirmationService. Aksi halde her tab
516
+ // kendi instance'ına sahip olur → host'tan tetiklenen toast MFE tab'ında (ya da tersi)
517
+ // görünmez. Shared instance ile tüm `<p-toast key="toast-root">` container'ları aynı kuyruğu dinler.
518
+ { provide: MessageService, useFactory: () => sharedAppRef.injector.get(MessageService) },
519
+ { provide: ConfirmationService, useFactory: () => sharedAppRef.injector.get(ConfirmationService) }
520
+ ];
521
+ const appComponentPromise = appComponentLoader();
522
+ class MFEAppElement extends HTMLElement {
523
+ constructor() {
524
+ super(...arguments);
525
+ this.childInjector = null;
526
+ this.compRef = null;
527
+ this.isBootstrapping = false;
528
+ this.destroyTimer = null;
529
+ }
530
+ async connectedCallback() {
531
+ // Strategy hidden container ↔ view arası taşımalarda re-bootstrap'ı önle —
532
+ // view zaten yaratıldıysa skip. destroyTimer pending ise iptal et.
533
+ if (this.compRef || this.isBootstrapping) {
534
+ if (this.destroyTimer) {
535
+ clearTimeout(this.destroyTimer);
536
+ this.destroyTimer = null;
537
+ }
538
+ return;
539
+ }
540
+ this.isBootstrapping = true;
541
+ try {
542
+ // Paylaşılan Application — ilk çağıran yaratır, diğerleri aynı promise'ı bekler.
543
+ if (!sharedAppPromise) {
544
+ sharedAppPromise = createApplication(sharedBaseConfig);
545
+ }
546
+ const [appRef, AppComponent] = await Promise.all([sharedAppPromise, appComponentPromise]);
547
+ sharedAppRef = appRef;
548
+ // Bu tab için izole Router stack'i barındıran child injector.
549
+ const tabId = this.getAttribute('aril-tab-id') ?? '';
550
+ this.childInjector = createEnvironmentInjector(childProviders, appRef.injector, `mfe:${_appName}:${tabId || 'pending'}`);
551
+ // [Hibrit izolasyon guard — kalıcı] `ɵINJECTOR_SCOPE:'root'` ile child injector'ın
552
+ // KENDİ Router + ChildrenOutletContexts'i olması, tab izolasyonunun temelidir
553
+ // ("1 Router : 1 outlet"). Bu private API Angular upgrade'inde davranış değiştirirse
554
+ // burada erken yakalanır; aksi halde "1 Router : N outlet" bug'ı sessizce geri döner.
555
+ if (isDevMode() && this.childInjector.get(Router) === appRef.injector.get(Router)) {
556
+ console.error(`[boot:${_appName}] HİBRİT İZOLASYON BOZULDU: child Router shared root ile aynı instance! ` +
557
+ `ɵINJECTOR_SCOPE davranışı değişmiş olabilir (Angular upgrade?) — tab izolasyonu çalışmaz.`);
558
+ }
559
+ // AppComponent'i child injector context'inde yarat → inject(Router)/LocationStrategy
560
+ // child-local; inject(MfeBridge)/HttpClient/Keycloak/TranslocoService vb. parent'tan
561
+ // paylaşımlı. `attachView` shared app'in change detection döngüsüne bağlar. (`bootstrap`
562
+ // değil: APP_BOOTSTRAP_LISTENER çalışmaz, child Router'ın initial navigation'ını
563
+ // AppComponent host-Router sync'i `safeNavigate` ile yapıyor.)
564
+ this.compRef = createComponent(AppComponent, {
565
+ environmentInjector: this.childInjector,
566
+ hostElement: this
567
+ });
568
+ appRef.attachView(this.compRef.hostView);
569
+ // Başarılı boot: guard artık `compRef` üzerinden çalışır → `isBootstrapping`'i bırak.
570
+ // (await sırasında disconnect olup hata oluşmazsa flag takılı kalmasın; aksi halde
571
+ // reconnect'te guard erken return edip tab'ı kalıcı boş bırakır.)
572
+ this.isBootstrapping = false;
573
+ }
574
+ catch (err) {
575
+ console.error(`[boot:${_appName}] application bootstrap hatası:`, err);
576
+ this.isBootstrapping = false;
577
+ // sharedApp henüz set edilmediyse (createApplication başarısız) promise'ı sıfırla ki
578
+ // sonraki tab retry edebilsin — aksi halde rejected promise closure'da kalıcı kalır ve
579
+ // remote sayfa yenilemeden bir daha boot edilemez. (createComponent hatasında
580
+ // sharedAppRef zaten set'tir; o durumda promise korunur, app yeniden yaratılmaz.)
581
+ if (!sharedAppRef)
582
+ sharedAppPromise = null;
583
+ }
584
+ }
585
+ disconnectedCallback() {
586
+ // Strategy hidden container ↔ view arası taşımalarda `removeChild` + `appendChild`
587
+ // ardışık olduğu için disconnectedCallback parent değişimiyle tetiklenir — element
588
+ // gerçekten destroy edilmiyor. `preserveWebComponentElement` öncesinde Strategy
589
+ // `__arilPreserveDuringDetach` flag'i set ediyor; o flag varsa view korunur.
590
+ const preserveFlag = this.__arilPreserveDuringDetach;
591
+ if (preserveFlag) {
592
+ return;
593
+ }
594
+ // Flag yok → gerçek destroy. Async re-connect ihtimaline karşı microtask sınırlı
595
+ // defansif gecikme; bir sonraki tick'te hâlâ disconnected mı diye son kontrol.
596
+ if (this.destroyTimer)
597
+ clearTimeout(this.destroyTimer);
598
+ this.destroyTimer = setTimeout(() => {
599
+ if (!this.isConnected && this.compRef) {
600
+ console.log(`[boot:${_appName}] gerçek destroy → view + child injector destroy`);
601
+ // Shared app'e ASLA dokunma; sadece bu tab'ın view'ını ve child injector'ını yık.
602
+ if (sharedAppRef)
603
+ sharedAppRef.detachView(this.compRef.hostView);
604
+ this.compRef.destroy();
605
+ this.childInjector?.destroy();
606
+ this.compRef = null;
607
+ this.childInjector = null;
608
+ this.isBootstrapping = false;
609
+ }
610
+ this.destroyTimer = null;
611
+ }, 0);
612
+ }
613
+ }
614
+ try {
615
+ customElements.define(`app-${appName}`, MFEAppElement);
616
+ }
617
+ catch (e) {
618
+ if (e instanceof DOMException && e.name === 'NotSupportedError') {
619
+ console.warn(`[boot:${appName}] custom element zaten tanımlı, define atlandı`);
620
+ return;
621
+ }
622
+ throw e;
623
+ }
624
+ };
625
+
626
+ /**
627
+ * Generated bundle index. Do not edit.
628
+ */
629
+
630
+ export { appName as a, boot as b };
631
+ //# sourceMappingURL=aril-boot-mfe-aril-boot-mfe-KFO_X7yR.mjs.map