uni-manager 0.1.47 → 0.1.49
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/fesm2022/uni-manager-error.mjs +17 -14
- package/fesm2022/uni-manager-error.mjs.map +1 -1
- package/fesm2022/uni-manager-http.mjs +154 -172
- package/fesm2022/uni-manager-http.mjs.map +1 -1
- package/fesm2022/uni-manager-locale.mjs +1 -1
- package/fesm2022/uni-manager-locale.mjs.map +1 -1
- package/fesm2022/uni-manager-toast.mjs +11 -3
- package/fesm2022/uni-manager-toast.mjs.map +1 -1
- package/package.json +3 -3
- package/types/uni-manager-error.d.ts +8 -6
- package/types/uni-manager-http.d.ts +24 -3
- package/types/uni-manager-toast.d.ts +1 -4
|
@@ -1,12 +1,22 @@
|
|
|
1
|
-
import { distinctUntilChanged, map
|
|
1
|
+
import { BehaviorSubject, distinctUntilChanged, map } from 'rxjs';
|
|
2
2
|
|
|
3
|
-
/* eslint-disable unicorn/consistent-class-member-order */
|
|
4
3
|
class UniErrorManager {
|
|
4
|
+
/* ------------------------------------------------------------------------------- */
|
|
5
|
+
/* ------------------------------------ Store ------------------------------------ */
|
|
6
|
+
/* ------------------------------------------------------------------------------- */
|
|
7
|
+
/** Store privato (Subject) */
|
|
8
|
+
static { this.store = new BehaviorSubject(new Map()); }
|
|
9
|
+
/** Store pubblico (Observable) */
|
|
10
|
+
static { this.store$ = this.store.asObservable(); }
|
|
5
11
|
/* ------------------------------------------------------------------------------- */
|
|
6
12
|
/* --------------------------------- Metodi: get --------------------------------- */
|
|
7
13
|
/* ------------------------------------------------------------------------------- */
|
|
14
|
+
/** Ottiene lo stato attuale della Map senza dover sottoscrivere l'observable */
|
|
15
|
+
static get currentValue() {
|
|
16
|
+
return this.store.getValue();
|
|
17
|
+
}
|
|
8
18
|
/** Restituisce la lista degli errori visibili */
|
|
9
|
-
static get
|
|
19
|
+
static get errors$() {
|
|
10
20
|
return this.store$.pipe(distinctUntilChanged((prev, curr) => {
|
|
11
21
|
// Se la dimensione differisce, le mappe sono strutturalmente diverse
|
|
12
22
|
if (prev.size !== curr.size)
|
|
@@ -39,18 +49,11 @@ class UniErrorManager {
|
|
|
39
49
|
}
|
|
40
50
|
/** Restituisce se lo store ha errori visibili o meno */
|
|
41
51
|
static get hasErrors$() {
|
|
42
|
-
return this.
|
|
52
|
+
return this.errors$.pipe(map((errorsList) => errorsList.length > 0), distinctUntilChanged());
|
|
43
53
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
/** Store privato (Subject) */
|
|
48
|
-
static { this.store = new BehaviorSubject(new Map()); }
|
|
49
|
-
/** Store pubblico (Observable) */
|
|
50
|
-
static { this.store$ = this.store.asObservable(); }
|
|
51
|
-
/** Ottiene lo stato attuale della Map senza dover sottoscrivere l'observable */
|
|
52
|
-
static get currentValue() {
|
|
53
|
-
return this.store.getValue();
|
|
54
|
+
/** Restituisce se lo store ha errori visibili */
|
|
55
|
+
static get hasVisibleErrors$() {
|
|
56
|
+
return this.errors$.pipe(map((errorsList) => errorsList.some((x) => x.isVisible)), distinctUntilChanged());
|
|
54
57
|
}
|
|
55
58
|
/* ------------------------------------------------------------------------------- */
|
|
56
59
|
/* -------------------------------- Metodi: store -------------------------------- */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uni-manager-error.mjs","sources":["../../../projects/uni-manager/error/manager.ts","../../../projects/uni-manager/error/uni-manager-error.ts"],"sourcesContent":["/* eslint-disable unicorn/consistent-class-member-order */\r\nimport { BehaviorSubject, distinctUntilChanged, map, Observable } from 'rxjs';\r\nimport type { ErrorStore, IUniFeError, IUniHttpError } from 'uni-model-type/type';\r\n\r\nexport class UniErrorManager {\r\n /* ------------------------------------------------------------------------------- */\r\n /* --------------------------------- Metodi: get --------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Restituisce la lista degli errori visibili */\r\n public static get errorStoreItems$(): Observable<({ id: string } & ErrorStore)[]> {\r\n return this.store$.pipe(\r\n distinctUntilChanged((prev, curr) => {\r\n // Se la dimensione differisce, le mappe sono strutturalmente diverse\r\n if (prev.size !== curr.size) return false;\r\n\r\n // Verifica puntuale dello stato di ciascun elemento per evitare la conversione in array\r\n for (const [id, prevItem] of prev) {\r\n const currentItem = curr.get(id);\r\n\r\n // Se l'elemento non esiste nella nuova mappa, viene rilevato un cambiamento\r\n if (!currentItem) return false;\r\n\r\n // Se varia lo stato di visibilità o il numero di eventi in cronologia, viene rilevato un cambiamento\r\n if (prevItem.isVisible !== currentItem.isVisible) return false;\r\n if (prevItem.historyItems.length !== currentItem.historyItems.length) return false;\r\n }\r\n\r\n // Nessuna variazione rilevata tra le due mappe\r\n return true;\r\n }),\r\n map((storeMap) => {\r\n const visibleErrors: ({ id: string } & ErrorStore)[] = [];\r\n for (const [id, item] of storeMap) {\r\n visibleErrors.push({ ...item, id });\r\n }\r\n return visibleErrors.toSorted((a, b) => {\r\n const lastTimestampA = a.historyItems.at(-1)?.timestamp ?? 0;\r\n const lastTimestampB = b.historyItems.at(-1)?.timestamp ?? 0;\r\n return lastTimestampB - lastTimestampA;\r\n });\r\n }),\r\n );\r\n }\r\n\r\n /** Restituisce se lo store ha errori visibili o meno */\r\n public static get hasErrors$(): Observable<boolean> {\r\n return this.errorStoreItems$.pipe(\r\n map((errorsList) => errorsList.length > 0),\r\n distinctUntilChanged(),\r\n );\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* ------------------------------------ Store ------------------------------------ */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Store privato (Subject) */\r\n private static store = new BehaviorSubject<Map<string, ErrorStore>>(new Map());\r\n\r\n /** Store pubblico (Observable) */\r\n public static store$: Observable<Map<string, ErrorStore>> = this.store.asObservable();\r\n\r\n /** Ottiene lo stato attuale della Map senza dover sottoscrivere l'observable */\r\n public static get currentValue(): Map<string, ErrorStore> {\r\n return this.store.getValue();\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: store -------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Aggiunge o aggiorna un errore nello store (lo rende automaticamente visibile).\r\n */\r\n public static add(id: string, error: IUniHttpError | IUniFeError): void {\r\n // Recupera l'ultimo stato (Map)\r\n const oldMap = this.currentValue;\r\n\r\n // Tenta di recuperare l'oggetto corrente\r\n const oldItem = oldMap.get(id);\r\n\r\n // Crea il nuovo oggetto\r\n const message = (\r\n error.type === 'be' && error.innerException ? error.innerException : error.exception\r\n ).message;\r\n const newItem: ErrorStore = {\r\n uniError: error,\r\n historyItems: [...(oldItem?.historyItems ?? []), { message, timestamp: Date.now() }],\r\n isVisible: true,\r\n isOpen: false,\r\n isCopied: false,\r\n isSaved: false,\r\n };\r\n\r\n // Crea una nuova istanza della Map\r\n const newMap = new Map(oldMap);\r\n newMap.set(id, newItem);\r\n\r\n // Aggiorna il nuovo stato notificando l'observer\r\n this.store.next(newMap);\r\n }\r\n\r\n /**\r\n * Nasconde un errore tramite ID senza eliminarlo dallo store (soft-delete)\r\n */\r\n public static hide(id: string): void {\r\n // Recupera l'ultimo stato (Map)\r\n const oldMap = this.currentValue;\r\n\r\n // Tenta di recuperare l'oggetto corrente\r\n const oldItem = oldMap.get(id);\r\n\r\n // Controllo: se non è presente l'item allora termina\r\n if (!oldItem) return;\r\n\r\n // Crea una nuova istanza della Map\r\n const newMap = new Map(oldMap);\r\n newMap.set(id, { ...oldItem, isVisible: false });\r\n\r\n // Aggiorna il nuovo stato notificando l'observer\r\n this.store.next(newMap);\r\n }\r\n\r\n /**\r\n * Nasconde tutti gli errori attualmente presenti nello store\r\n */\r\n public static hideAll(): void {\r\n // Recupera l'ultimo stato (Map)\r\n const oldMap = this.currentValue;\r\n\r\n // Controllo: se lo store è vuoto allora termina\r\n if (oldMap.size === 0) return;\r\n\r\n // Crea una nuova istanza della Map\r\n const newMap = new Map<string, ErrorStore>();\r\n for (const [key, value] of oldMap) {\r\n newMap.set(key, { ...value, isVisible: false });\r\n }\r\n\r\n // Aggiorna il nuovo stato notificando l'observer\r\n this.store.next(newMap);\r\n }\r\n\r\n /**\r\n * Rimuove definitivamente un errore tramite ID dallo store\r\n */\r\n public static remove(id: string): void {\r\n // Recupera l'ultimo stato (Map)\r\n const oldMap = this.currentValue;\r\n\r\n // Controllo: se non è presente l'item allora termina\r\n if (!oldMap.has(id)) return;\r\n\r\n // Crea una nuova istanza della Map\r\n const newMap = new Map(oldMap);\r\n newMap.delete(id);\r\n\r\n // Aggiorna il nuovo stato notificando l'observer\r\n this.store.next(newMap);\r\n }\r\n\r\n /**\r\n * Svuota completamente il map degli errori (hard-delete)\r\n */\r\n public static removeAll(): void {\r\n // Crea una nuova istanza della Map\r\n const newMap = new Map<string, ErrorStore>();\r\n\r\n // Aggiorna il nuovo stato notificando l'observer\r\n this.store.next(newMap);\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"uni-manager-error.mjs","sources":["../../../projects/uni-manager/error/manager.ts","../../../projects/uni-manager/error/uni-manager-error.ts"],"sourcesContent":["import { BehaviorSubject, distinctUntilChanged, map, Observable } from 'rxjs';\r\nimport type { ErrorStore, IUniFeError, IUniHttpError } from 'uni-model-type/type';\r\n\r\nexport class UniErrorManager {\r\n /* ------------------------------------------------------------------------------- */\r\n /* ------------------------------------ Store ------------------------------------ */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Store privato (Subject) */\r\n private static store = new BehaviorSubject<Map<string, ErrorStore>>(new Map());\r\n\r\n /** Store pubblico (Observable) */\r\n public static store$: Observable<Map<string, ErrorStore>> = this.store.asObservable();\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* --------------------------------- Metodi: get --------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Ottiene lo stato attuale della Map senza dover sottoscrivere l'observable */\r\n public static get currentValue(): Map<string, ErrorStore> {\r\n return this.store.getValue();\r\n }\r\n\r\n /** Restituisce la lista degli errori visibili */\r\n public static get errors$(): Observable<({ id: string } & ErrorStore)[]> {\r\n return this.store$.pipe(\r\n distinctUntilChanged((prev, curr) => {\r\n // Se la dimensione differisce, le mappe sono strutturalmente diverse\r\n if (prev.size !== curr.size) return false;\r\n\r\n // Verifica puntuale dello stato di ciascun elemento per evitare la conversione in array\r\n for (const [id, prevItem] of prev) {\r\n const currentItem = curr.get(id);\r\n\r\n // Se l'elemento non esiste nella nuova mappa, viene rilevato un cambiamento\r\n if (!currentItem) return false;\r\n\r\n // Se varia lo stato di visibilità o il numero di eventi in cronologia, viene rilevato un cambiamento\r\n if (prevItem.isVisible !== currentItem.isVisible) return false;\r\n if (prevItem.historyItems.length !== currentItem.historyItems.length) return false;\r\n }\r\n\r\n // Nessuna variazione rilevata tra le due mappe\r\n return true;\r\n }),\r\n map((storeMap) => {\r\n const visibleErrors: ({ id: string } & ErrorStore)[] = [];\r\n for (const [id, item] of storeMap) {\r\n visibleErrors.push({ ...item, id });\r\n }\r\n return visibleErrors.toSorted((a, b) => {\r\n const lastTimestampA = a.historyItems.at(-1)?.timestamp ?? 0;\r\n const lastTimestampB = b.historyItems.at(-1)?.timestamp ?? 0;\r\n return lastTimestampB - lastTimestampA;\r\n });\r\n }),\r\n );\r\n }\r\n\r\n /** Restituisce se lo store ha errori visibili o meno */\r\n public static get hasErrors$(): Observable<boolean> {\r\n return this.errors$.pipe(\r\n map((errorsList) => errorsList.length > 0),\r\n distinctUntilChanged(),\r\n );\r\n }\r\n\r\n /** Restituisce se lo store ha errori visibili */\r\n public static get hasVisibleErrors$(): Observable<boolean> {\r\n return this.errors$.pipe(\r\n map((errorsList) => errorsList.some((x) => x.isVisible)),\r\n distinctUntilChanged(),\r\n );\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: store -------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Aggiunge o aggiorna un errore nello store (lo rende automaticamente visibile).\r\n */\r\n public static add(id: string, error: IUniHttpError | IUniFeError): void {\r\n // Recupera l'ultimo stato (Map)\r\n const oldMap = this.currentValue;\r\n\r\n // Tenta di recuperare l'oggetto corrente\r\n const oldItem = oldMap.get(id);\r\n\r\n // Crea il nuovo oggetto\r\n const message = (\r\n error.type === 'be' && error.innerException ? error.innerException : error.exception\r\n ).message;\r\n const newItem: ErrorStore = {\r\n uniError: error,\r\n historyItems: [...(oldItem?.historyItems ?? []), { message, timestamp: Date.now() }],\r\n isVisible: true,\r\n isOpen: false,\r\n isCopied: false,\r\n isSaved: false,\r\n };\r\n\r\n // Crea una nuova istanza della Map\r\n const newMap = new Map(oldMap);\r\n newMap.set(id, newItem);\r\n\r\n // Aggiorna il nuovo stato notificando l'observer\r\n this.store.next(newMap);\r\n }\r\n\r\n /**\r\n * Nasconde un errore tramite ID senza eliminarlo dallo store (soft-delete)\r\n */\r\n public static hide(id: string): void {\r\n // Recupera l'ultimo stato (Map)\r\n const oldMap = this.currentValue;\r\n\r\n // Tenta di recuperare l'oggetto corrente\r\n const oldItem = oldMap.get(id);\r\n\r\n // Controllo: se non è presente l'item allora termina\r\n if (!oldItem) return;\r\n\r\n // Crea una nuova istanza della Map\r\n const newMap = new Map(oldMap);\r\n newMap.set(id, { ...oldItem, isVisible: false });\r\n\r\n // Aggiorna il nuovo stato notificando l'observer\r\n this.store.next(newMap);\r\n }\r\n\r\n /**\r\n * Nasconde tutti gli errori attualmente presenti nello store\r\n */\r\n public static hideAll(): void {\r\n // Recupera l'ultimo stato (Map)\r\n const oldMap = this.currentValue;\r\n\r\n // Controllo: se lo store è vuoto allora termina\r\n if (oldMap.size === 0) return;\r\n\r\n // Crea una nuova istanza della Map\r\n const newMap = new Map<string, ErrorStore>();\r\n for (const [key, value] of oldMap) {\r\n newMap.set(key, { ...value, isVisible: false });\r\n }\r\n\r\n // Aggiorna il nuovo stato notificando l'observer\r\n this.store.next(newMap);\r\n }\r\n\r\n /**\r\n * Rimuove definitivamente un errore tramite ID dallo store\r\n */\r\n public static remove(id: string): void {\r\n // Recupera l'ultimo stato (Map)\r\n const oldMap = this.currentValue;\r\n\r\n // Controllo: se non è presente l'item allora termina\r\n if (!oldMap.has(id)) return;\r\n\r\n // Crea una nuova istanza della Map\r\n const newMap = new Map(oldMap);\r\n newMap.delete(id);\r\n\r\n // Aggiorna il nuovo stato notificando l'observer\r\n this.store.next(newMap);\r\n }\r\n\r\n /**\r\n * Svuota completamente il map degli errori (hard-delete)\r\n */\r\n public static removeAll(): void {\r\n // Crea una nuova istanza della Map\r\n const newMap = new Map<string, ErrorStore>();\r\n\r\n // Aggiorna il nuovo stato notificando l'observer\r\n this.store.next(newMap);\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { switchMap, mergeMap, concatMap, exhaustMap, throwError, of, EMPTY, defer, from, tap, catchError, finalize, timer, distinctUntilChanged,
|
|
1
|
+
import { switchMap, mergeMap, concatMap, exhaustMap, throwError, of, EMPTY, defer, from, tap, catchError, finalize, timer, distinctUntilChanged, BehaviorSubject, map } from 'rxjs';
|
|
2
2
|
import { UniToastManager } from 'uni-manager/toast';
|
|
3
3
|
import isEqual from 'lodash-es/isEqual';
|
|
4
4
|
import { UniErrorManager } from 'uni-manager/error';
|
|
@@ -65,21 +65,21 @@ function http$(url, refType, config, promiseCallback) {
|
|
|
65
65
|
const http$ = from(promiseCallback());
|
|
66
66
|
return http$.pipe(tap({
|
|
67
67
|
subscribe: () => {
|
|
68
|
+
/* Creazione reference */
|
|
69
|
+
UniHttpManager.add(ref, new URL(url), refType);
|
|
68
70
|
/* Incrementa per il loader */
|
|
69
71
|
if (isLoaderActive) {
|
|
70
|
-
updateIsLoading(ref, 1);
|
|
72
|
+
UniHttpManager.updateIsLoading(ref, 1);
|
|
71
73
|
}
|
|
72
|
-
/* Creazione reference */
|
|
73
|
-
add(ref, new URL(url), refType);
|
|
74
74
|
},
|
|
75
75
|
unsubscribe: () => {
|
|
76
76
|
/* Disattivazione loader per sicurezza se il flusso si interrompe prima della risposta */
|
|
77
77
|
if (isLoaderActive) {
|
|
78
|
-
updateIsLoading(ref, -1);
|
|
78
|
+
UniHttpManager.updateIsLoading(ref, -1);
|
|
79
79
|
isLoaderActive = false;
|
|
80
80
|
}
|
|
81
81
|
/* Rimozione reference */
|
|
82
|
-
remove(ref);
|
|
82
|
+
UniHttpManager.remove(ref);
|
|
83
83
|
},
|
|
84
84
|
next: (res) => {
|
|
85
85
|
/* Mostra toast (se presente) */
|
|
@@ -89,13 +89,13 @@ function http$(url, refType, config, promiseCallback) {
|
|
|
89
89
|
},
|
|
90
90
|
}), catchError((error) => {
|
|
91
91
|
// Aggiorna la ref nella map
|
|
92
|
-
updateHasError(ref, true);
|
|
92
|
+
UniHttpManager.updateHasError(ref, true);
|
|
93
93
|
/* Gestione errore */
|
|
94
94
|
return errorHandler(ref, error, PollingErrorMode.STOP);
|
|
95
95
|
}), finalize(() => {
|
|
96
96
|
/* Decrementa per il loader */
|
|
97
97
|
if (isLoaderActive) {
|
|
98
|
-
updateIsLoading(ref, -1);
|
|
98
|
+
UniHttpManager.updateIsLoading(ref, -1);
|
|
99
99
|
isLoaderActive = false;
|
|
100
100
|
}
|
|
101
101
|
}));
|
|
@@ -112,18 +112,18 @@ function httpPolling$(url, config, promiseFactory) {
|
|
|
112
112
|
const source$ = timer$.pipe(tap({
|
|
113
113
|
subscribe: () => {
|
|
114
114
|
/* Creazione reference */
|
|
115
|
-
add(ref, new URL(url), 'polling');
|
|
115
|
+
UniHttpManager.add(ref, new URL(url), 'polling');
|
|
116
116
|
},
|
|
117
117
|
unsubscribe: () => {
|
|
118
118
|
/* Rimozione reference */
|
|
119
|
-
remove(ref);
|
|
119
|
+
UniHttpManager.remove(ref);
|
|
120
120
|
},
|
|
121
121
|
}), operatorHandler(operator)((index) => {
|
|
122
122
|
// Il loader è attivo solo al primo giro se non è esplicitamente false
|
|
123
123
|
let isLoaderActive = index === 0 && firstIteration?.hasLoader !== false;
|
|
124
124
|
/* Incrementa per il loader */
|
|
125
125
|
if (isLoaderActive) {
|
|
126
|
-
updateIsLoading(ref, 1);
|
|
126
|
+
UniHttpManager.updateIsLoading(ref, 1);
|
|
127
127
|
}
|
|
128
128
|
return defer(() => {
|
|
129
129
|
const http$ = from(promiseFactory());
|
|
@@ -131,7 +131,7 @@ function httpPolling$(url, config, promiseFactory) {
|
|
|
131
131
|
unsubscribe: () => {
|
|
132
132
|
/* Disattivazione loader per sicurezza se il flusso si interrompe prima della risposta */
|
|
133
133
|
if (isLoaderActive) {
|
|
134
|
-
updateIsLoading(ref, -1);
|
|
134
|
+
UniHttpManager.updateIsLoading(ref, -1);
|
|
135
135
|
isLoaderActive = false;
|
|
136
136
|
}
|
|
137
137
|
},
|
|
@@ -144,7 +144,7 @@ function httpPolling$(url, config, promiseFactory) {
|
|
|
144
144
|
}
|
|
145
145
|
/* Prima risposta: loader */
|
|
146
146
|
if (isLoaderActive) {
|
|
147
|
-
updateIsLoading(ref, -1);
|
|
147
|
+
UniHttpManager.updateIsLoading(ref, -1);
|
|
148
148
|
isLoaderActive = false;
|
|
149
149
|
}
|
|
150
150
|
/* Prima risposta: toast */
|
|
@@ -154,18 +154,18 @@ function httpPolling$(url, config, promiseFactory) {
|
|
|
154
154
|
}
|
|
155
155
|
/* Meccanismo di ripristino automatico: se il polling torna in salute, cancella l'errore dallo store e nasconde i relativi messaggi a schermo */
|
|
156
156
|
if (errorMode === PollingErrorMode.IGNORE_WITH_ERROR) {
|
|
157
|
-
updateHasError(ref, false);
|
|
157
|
+
UniHttpManager.updateHasError(ref, false);
|
|
158
158
|
UniErrorManager.remove(ref);
|
|
159
159
|
}
|
|
160
160
|
},
|
|
161
161
|
}), catchError((error) => {
|
|
162
162
|
/* Disattivazione loader in caso di errore al primo giro */
|
|
163
163
|
if (isLoaderActive) {
|
|
164
|
-
updateIsLoading(ref, -1);
|
|
164
|
+
UniHttpManager.updateIsLoading(ref, -1);
|
|
165
165
|
isLoaderActive = false;
|
|
166
166
|
}
|
|
167
167
|
// Aggiorna la ref nella map
|
|
168
|
-
updateHasError(ref, true);
|
|
168
|
+
UniHttpManager.updateHasError(ref, true);
|
|
169
169
|
/* Gestione errore */
|
|
170
170
|
return errorHandler(ref, error, errorMode);
|
|
171
171
|
}));
|
|
@@ -175,97 +175,49 @@ function httpPolling$(url, config, promiseFactory) {
|
|
|
175
175
|
? source$.pipe(distinctUntilChanged((prev, cur) => isEqual(prev, cur)))
|
|
176
176
|
: source$;
|
|
177
177
|
}
|
|
178
|
-
|
|
179
|
-
/*
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
function add(id, url, type) {
|
|
186
|
-
// Recupera l'ultimo stato (Map)
|
|
187
|
-
const oldMap = UniHttpManager.currentValue;
|
|
188
|
-
// Controllo: se è presente l'item allora termina
|
|
189
|
-
if (oldMap.get(id))
|
|
190
|
-
return;
|
|
191
|
-
// Crea il nuovo oggetto
|
|
192
|
-
const newItemMap = {
|
|
193
|
-
type,
|
|
194
|
-
lineId: undefined,
|
|
195
|
-
url,
|
|
196
|
-
hasError: false,
|
|
197
|
-
pendingCount: 0,
|
|
198
|
-
};
|
|
199
|
-
// Crea una nuova istanza della Map
|
|
200
|
-
const newMap = new Map(oldMap);
|
|
201
|
-
newMap.set(id, newItemMap);
|
|
202
|
-
// Aggiorna il nuovo stato notificando l'observer
|
|
203
|
-
UniHttpManager.store.next(newMap);
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Rimuove un http ref tramite ID
|
|
207
|
-
*/
|
|
208
|
-
function remove(id) {
|
|
209
|
-
// Recupera l'ultimo stato (Map)
|
|
210
|
-
const oldMap = UniHttpManager.currentValue;
|
|
211
|
-
// Controllo: se non è presente l'item allora termina
|
|
212
|
-
if (!oldMap.has(id))
|
|
213
|
-
return;
|
|
214
|
-
// Aggiorna store
|
|
215
|
-
const newMap = new Map(oldMap);
|
|
216
|
-
newMap.delete(id);
|
|
217
|
-
UniHttpManager.store.next(newMap);
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Aggiorna il contatore delle chiamate pendenti per una specifica ref.
|
|
221
|
-
* Incrementa o decrementa 'pendingCount' garantendo che non scenda mai sotto lo zero.
|
|
222
|
-
* Se la ref non esiste, l'operazione viene ignorata.
|
|
223
|
-
*/
|
|
224
|
-
function updateIsLoading(id, delta) {
|
|
225
|
-
// Recupera l'ultimo stato (Map)
|
|
226
|
-
const oldMap = UniHttpManager.currentValue;
|
|
227
|
-
// Controllo: se non è presente l'item allora termina
|
|
228
|
-
const oldItem = oldMap.get(id);
|
|
229
|
-
if (!oldItem)
|
|
178
|
+
|
|
179
|
+
/* eslint-disable unicorn/no-declarations-before-early-exit */
|
|
180
|
+
async function executeHttp(request) {
|
|
181
|
+
/* Esegue la chiamata HTTP */
|
|
182
|
+
const res = await execute(request);
|
|
183
|
+
/* Gestione dello stato 204: chiamata andata a buon fine ma senza dati di ritorno */
|
|
184
|
+
if (res.status === 204)
|
|
230
185
|
return;
|
|
231
|
-
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
// Aggiorna il nuovo stato notificando l'observer
|
|
240
|
-
UniHttpManager.store.next(newMap);
|
|
186
|
+
/* Estrae il contenuto come testo */
|
|
187
|
+
const text = await res.text();
|
|
188
|
+
/* Controllo: se il testo è vuoto ('') lancia errore */
|
|
189
|
+
if (!text || text.trim().length === 0) {
|
|
190
|
+
throw response204Error(request, res);
|
|
191
|
+
}
|
|
192
|
+
/* Parsa manualmente il testo, dato che lo stream è stato già letto */
|
|
193
|
+
return JSON.parse(text);
|
|
241
194
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
if (
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
195
|
+
async function executeBlob(request) {
|
|
196
|
+
/* Esegue la chiamata HTTP */
|
|
197
|
+
const res = await execute(request);
|
|
198
|
+
/* Gestione dello stato 204: se la chiamata andata a buon fine ma senza dati di ritorno lancia errore */
|
|
199
|
+
if (res.status === 204) {
|
|
200
|
+
throw response204Error(request, res);
|
|
201
|
+
}
|
|
202
|
+
/* Estrae il contenuto come Blob direttamente */
|
|
203
|
+
const blob = await res.blob();
|
|
204
|
+
/* Controllo: se il blob è vuoto (0 byte) lancia errore */
|
|
205
|
+
if (blob.size === 0) {
|
|
206
|
+
throw response204Error(request, res);
|
|
207
|
+
}
|
|
208
|
+
/* Estrae il nome del file dall'header */
|
|
209
|
+
const disposition = res.headers.get('Content-Disposition');
|
|
210
|
+
let name = '';
|
|
211
|
+
if (disposition) {
|
|
212
|
+
const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(disposition);
|
|
213
|
+
if (!!matches && matches[1]) {
|
|
214
|
+
name = matches[1].replaceAll(/['"]/g, '');
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return { blob, name };
|
|
264
218
|
}
|
|
265
|
-
|
|
266
|
-
/* eslint-disable unicorn/no-declarations-before-early-exit */
|
|
267
219
|
// =============================================================================
|
|
268
|
-
//
|
|
220
|
+
// HELPERS
|
|
269
221
|
// =============================================================================
|
|
270
222
|
/**
|
|
271
223
|
* Esegue una richiesta HTTP nativa gestendo l'imbuto dei 4 casi d'errore.
|
|
@@ -391,61 +343,9 @@ async function execute(request) {
|
|
|
391
343
|
throw error;
|
|
392
344
|
}
|
|
393
345
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
/* Gestione dello stato 204: chiamata andata a buon fine ma senza dati di ritorno */
|
|
398
|
-
if (res.status === 204)
|
|
399
|
-
return;
|
|
400
|
-
/* Estrae il contenuto come testo */
|
|
401
|
-
const text = await res.text();
|
|
402
|
-
/* Controllo: se il testo è vuoto ('') lancia errore */
|
|
403
|
-
if (!text || text.trim().length === 0) {
|
|
404
|
-
throw response204Error(request, res);
|
|
405
|
-
}
|
|
406
|
-
/* Parsa manualmente il testo, dato che lo stream è stato già letto */
|
|
407
|
-
return JSON.parse(text);
|
|
408
|
-
}
|
|
409
|
-
async function executeBlob(request) {
|
|
410
|
-
/* Esegue la chiamata HTTP */
|
|
411
|
-
const res = await execute(request);
|
|
412
|
-
/* Gestione dello stato 204: se la chiamata andata a buon fine ma senza dati di ritorno lancia errore */
|
|
413
|
-
if (res.status === 204) {
|
|
414
|
-
throw response204Error(request, res);
|
|
415
|
-
}
|
|
416
|
-
/* Estrae il contenuto come Blob direttamente */
|
|
417
|
-
const blob = await res.blob();
|
|
418
|
-
/* Controllo: se il blob è vuoto (0 byte) lancia errore */
|
|
419
|
-
if (blob.size === 0) {
|
|
420
|
-
throw response204Error(request, res);
|
|
421
|
-
}
|
|
422
|
-
/* Estrae il nome del file dall'header */
|
|
423
|
-
const disposition = res.headers.get('Content-Disposition');
|
|
424
|
-
let name = '';
|
|
425
|
-
if (disposition) {
|
|
426
|
-
const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(disposition);
|
|
427
|
-
if (!!matches && matches[1]) {
|
|
428
|
-
name = matches[1].replaceAll(/['"]/g, '');
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
return { blob, name };
|
|
432
|
-
}
|
|
433
|
-
// export async function executeFile(request: Request, dispositionType: string): Promise<void> {
|
|
434
|
-
// const url: URL = new URL(request.url);
|
|
435
|
-
// const authHeader = request.headers.get('Authorization');
|
|
436
|
-
// if (authHeader && authHeader.startsWith('Bearer ')) {
|
|
437
|
-
// const token = authHeader.slice(7);
|
|
438
|
-
// url.searchParams.append('token', token); // Il backend dovrà accettare il token anche da query string
|
|
439
|
-
// }
|
|
440
|
-
// if (dispositionType === 'inline') {
|
|
441
|
-
// UniFileManager.openPreviewInNewTab(url);
|
|
442
|
-
// } else {
|
|
443
|
-
// UniFileManager.download(url);
|
|
444
|
-
// }
|
|
445
|
-
// }
|
|
446
|
-
// =============================================================================
|
|
447
|
-
// HELPERS
|
|
448
|
-
// =============================================================================
|
|
346
|
+
/**
|
|
347
|
+
* Gestione errore in caso di assenza di risposta quando invece era prevista
|
|
348
|
+
*/
|
|
449
349
|
function response204Error(request, res) {
|
|
450
350
|
return new UniHttpError({
|
|
451
351
|
type: 'be',
|
|
@@ -649,25 +549,13 @@ function normalizeHttpBody(body, method, hasToKeepId) {
|
|
|
649
549
|
return Object.fromEntries(entries);
|
|
650
550
|
}
|
|
651
551
|
|
|
652
|
-
/* eslint-disable unicorn/
|
|
552
|
+
/* eslint-disable unicorn/prefer-iterator-to-array */
|
|
553
|
+
/* eslint-disable unicorn/prefer-iterator-helpers */
|
|
653
554
|
const CONFIG_TOAST_DEFAULT = {
|
|
654
555
|
type: 'success',
|
|
655
556
|
label: 'OperationCompleted',
|
|
656
557
|
};
|
|
657
558
|
class UniHttpManager {
|
|
658
|
-
/* ------------------------------------------------------------------------------- */
|
|
659
|
-
/* --------------------------------- Metodi: get --------------------------------- */
|
|
660
|
-
/* ------------------------------------------------------------------------------- */
|
|
661
|
-
/** Restituisce se lo store ha chiamate in attesa di risposta o meno */
|
|
662
|
-
static get hasWaitingRequests$() {
|
|
663
|
-
return this.store$.pipe(map((requestMap) => {
|
|
664
|
-
for (const x of requestMap.values()) {
|
|
665
|
-
if (x.pendingCount > 0)
|
|
666
|
-
return true;
|
|
667
|
-
}
|
|
668
|
-
return false;
|
|
669
|
-
}), distinctUntilChanged());
|
|
670
|
-
}
|
|
671
559
|
/* ------------------------------------------------------------------------------- */
|
|
672
560
|
/* ------------------------------------ Store ------------------------------------ */
|
|
673
561
|
/* ------------------------------------------------------------------------------- */
|
|
@@ -675,10 +563,17 @@ class UniHttpManager {
|
|
|
675
563
|
static { this.store = new BehaviorSubject(new Map()); }
|
|
676
564
|
/** Store pubblico (Observable) */
|
|
677
565
|
static { this.store$ = this.store.asObservable(); }
|
|
566
|
+
/* ------------------------------------------------------------------------------- */
|
|
567
|
+
/* --------------------------------- Metodi: get --------------------------------- */
|
|
568
|
+
/* ------------------------------------------------------------------------------- */
|
|
678
569
|
/** Ottiene lo stato attuale della Map senza dover sottoscrivere l'observable */
|
|
679
570
|
static get currentValue() {
|
|
680
571
|
return this.store.getValue();
|
|
681
572
|
}
|
|
573
|
+
/** Restituisce se lo store ha chiamate in attesa di risposta o meno */
|
|
574
|
+
static get hasWaitingRequests$() {
|
|
575
|
+
return this.store$.pipe(map((requestMap) => [...requestMap.values()].some((request) => request.pendingCount > 0)), distinctUntilChanged());
|
|
576
|
+
}
|
|
682
577
|
/* ------------------------------------------------------------------------------- */
|
|
683
578
|
/* -------------------------------- Metodi: setup -------------------------------- */
|
|
684
579
|
/* ------------------------------------------------------------------------------- */
|
|
@@ -690,6 +585,93 @@ class UniHttpManager {
|
|
|
690
585
|
this.hostname = hostname;
|
|
691
586
|
this.port = port;
|
|
692
587
|
}
|
|
588
|
+
/* ------------------------------------------------------------------------------- */
|
|
589
|
+
/* -------------------------------- Metodi: store -------------------------------- */
|
|
590
|
+
/* ------------------------------------------------------------------------------- */
|
|
591
|
+
/**
|
|
592
|
+
* Aggiunge una nuova ref nello store solo se non è già presente.
|
|
593
|
+
* Se l'ID esiste già, l'operazione viene interrotta per preservare il dato originale.
|
|
594
|
+
*/
|
|
595
|
+
static add(id, url, type) {
|
|
596
|
+
// Recupera l'ultimo stato (Map)
|
|
597
|
+
const oldMap = this.currentValue;
|
|
598
|
+
// Controllo: se è presente l'item allora termina
|
|
599
|
+
if (oldMap.get(id))
|
|
600
|
+
return;
|
|
601
|
+
// Crea il nuovo oggetto
|
|
602
|
+
const newItemMap = {
|
|
603
|
+
type,
|
|
604
|
+
lineId: undefined,
|
|
605
|
+
url,
|
|
606
|
+
hasError: false,
|
|
607
|
+
pendingCount: 0,
|
|
608
|
+
};
|
|
609
|
+
// Crea una nuova istanza della Map
|
|
610
|
+
const newMap = new Map(oldMap);
|
|
611
|
+
newMap.set(id, newItemMap);
|
|
612
|
+
// Aggiorna il nuovo stato notificando l'observer
|
|
613
|
+
this.store.next(newMap);
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Rimuove un http ref tramite ID
|
|
617
|
+
*/
|
|
618
|
+
static remove(id) {
|
|
619
|
+
// Recupera l'ultimo stato (Map)
|
|
620
|
+
const oldMap = this.currentValue;
|
|
621
|
+
// Controllo: se non è presente l'item allora termina
|
|
622
|
+
if (!oldMap.has(id))
|
|
623
|
+
return;
|
|
624
|
+
// Aggiorna store
|
|
625
|
+
const newMap = new Map(oldMap);
|
|
626
|
+
newMap.delete(id);
|
|
627
|
+
this.store.next(newMap);
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Aggiorna il contatore delle chiamate pendenti per una specifica ref.
|
|
631
|
+
* Incrementa o decrementa 'pendingCount' garantendo che non scenda mai sotto lo zero.
|
|
632
|
+
* Se la ref non esiste, l'operazione viene ignorata.
|
|
633
|
+
*/
|
|
634
|
+
static updateIsLoading(id, delta) {
|
|
635
|
+
// Recupera l'ultimo stato (Map)
|
|
636
|
+
const oldMap = this.currentValue;
|
|
637
|
+
// Controllo: se non è presente l'item allora termina
|
|
638
|
+
const oldItem = oldMap.get(id);
|
|
639
|
+
if (!oldItem)
|
|
640
|
+
return;
|
|
641
|
+
// Aggiorna l'oggetto
|
|
642
|
+
const newItemMap = {
|
|
643
|
+
...oldItem,
|
|
644
|
+
pendingCount: Math.max(0, oldItem.pendingCount + delta),
|
|
645
|
+
};
|
|
646
|
+
// Crea una nuova istanza della Map
|
|
647
|
+
const newMap = new Map(oldMap);
|
|
648
|
+
newMap.set(id, newItemMap);
|
|
649
|
+
// Aggiorna il nuovo stato notificando l'observer
|
|
650
|
+
this.store.next(newMap);
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Aggiorna lo stato di errore per una specifica ref.
|
|
654
|
+
* Se il valore di 'hasError' è identico a quello attuale o se la ref non esiste,
|
|
655
|
+
* l'operazione viene interrotta per evitare aggiornamenti inutili.
|
|
656
|
+
*/
|
|
657
|
+
static updateHasError(id, hasError) {
|
|
658
|
+
// Recupera l'ultimo stato (Map)
|
|
659
|
+
const oldMap = this.currentValue;
|
|
660
|
+
// Controllo: se non è presente l'item allora termina
|
|
661
|
+
const oldItem = oldMap.get(id);
|
|
662
|
+
if (!oldItem)
|
|
663
|
+
return;
|
|
664
|
+
// Controllo: se con lo stesso valore, salta
|
|
665
|
+
if (oldItem.hasError === hasError)
|
|
666
|
+
return;
|
|
667
|
+
// Aggiorna l'oggetto
|
|
668
|
+
const newItemMap = { ...oldItem, hasError };
|
|
669
|
+
// Crea una nuova istanza della Map
|
|
670
|
+
const newMap = new Map(oldMap);
|
|
671
|
+
newMap.set(id, newItemMap);
|
|
672
|
+
// Aggiorna il nuovo stato notificando l'observer
|
|
673
|
+
this.store.next(newMap);
|
|
674
|
+
}
|
|
693
675
|
static read$(config) {
|
|
694
676
|
/* Config */
|
|
695
677
|
const defaultRequestInit = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uni-manager-http.mjs","sources":["../../../projects/uni-manager/http/handler.ts","../../../projects/uni-manager/http/core.ts","../../../projects/uni-manager/http/execute.ts","../../../projects/uni-manager/http/utilities.ts","../../../projects/uni-manager/http/manager.ts","../../../projects/uni-manager/http/uni-manager-http.ts"],"sourcesContent":["import {\r\n EMPTY,\r\n Observable,\r\n OperatorFunction,\r\n concatMap,\r\n exhaustMap,\r\n mergeMap,\r\n of,\r\n switchMap,\r\n throwError,\r\n} from 'rxjs';\r\nimport { UniHttpError } from 'uni-error/http';\r\nimport { UniErrorManager } from 'uni-manager/error';\r\nimport { MapOperator, PollingErrorMode } from 'uni-model-type/enum';\r\n\r\nexport function operatorHandler<T>(\r\n operator: MapOperator,\r\n): (project: (value: number) => Observable<T>) => OperatorFunction<number, T> {\r\n // Gestione della concorrenza in base al parametro\r\n switch (operator) {\r\n case MapOperator.EXHAUST_MAP: {\r\n return (project) => exhaustMap(project);\r\n }\r\n case MapOperator.CONCAT_MAP: {\r\n return (project) => concatMap(project);\r\n }\r\n case MapOperator.MERGE_MAP: {\r\n return (project) => mergeMap(project);\r\n }\r\n case MapOperator.SWITCH_MAP: {\r\n return (project) => switchMap(project);\r\n }\r\n }\r\n}\r\n\r\nexport function errorHandler(\r\n ref: string,\r\n error: unknown,\r\n errorMode: PollingErrorMode,\r\n): Observable<never> {\r\n // Controllo: sia effettivamente un errore di tipo 'UniHttpError'\r\n if (error instanceof UniHttpError) {\r\n switch (errorMode) {\r\n case PollingErrorMode.IGNORE: {\r\n return of();\r\n }\r\n case PollingErrorMode.SKIP: {\r\n return EMPTY;\r\n }\r\n case PollingErrorMode.IGNORE_WITH_ERROR: {\r\n UniErrorManager.add(ref, error);\r\n return of();\r\n }\r\n case PollingErrorMode.STOP: {\r\n UniErrorManager.add(ref, error);\r\n return throwError(() => error);\r\n }\r\n }\r\n } else {\r\n return throwError(() => error);\r\n }\r\n}\r\n","/* eslint-disable unicorn/prefer-early-return */\r\nimport isEqual from 'lodash-es/isEqual';\r\nimport {\r\n Observable,\r\n catchError,\r\n defer,\r\n distinctUntilChanged,\r\n finalize,\r\n from,\r\n tap,\r\n timer,\r\n} from 'rxjs';\r\nimport { UniErrorManager } from 'uni-manager/error';\r\nimport { UniToastManager } from 'uni-manager/toast';\r\nimport { EmitValueMode, MapOperator, PollingErrorMode } from 'uni-model-type/enum';\r\nimport type { HttpConfig, HttpConfigPolling, HttpRef } from 'uni-model-type/type';\r\n\r\nimport { errorHandler, operatorHandler } from './handler';\r\nimport { UniHttpManager } from './manager';\r\n\r\n/* ------------------------------------------------------------------------------- */\r\n/* -------------------------------- Funzioni Core RxJS -------------------------- */\r\n/* ------------------------------------------------------------------------------- */\r\n/**\r\n * Gestisce l'esecuzione e il ciclo di vita di una singola richiesta HTTP.\r\n * Si occupa della registrazione della reference, della gestione dei loader, dei toast di successo e dell'intercettazione degli errori.\r\n */\r\nexport function http$<T>(\r\n url: string,\r\n refType: HttpRef['type'],\r\n config: HttpConfig<T>,\r\n promiseCallback: () => Promise<T>,\r\n): Observable<T> {\r\n /* Recupero configurazione */\r\n const { ref, toast, hasLoader } = config;\r\n\r\n // Usiamo un flag let per garantire che il loader venga spento una sola volta\r\n let isLoaderActive = hasLoader !== false;\r\n\r\n return defer(() => {\r\n const http$ = from(promiseCallback());\r\n return http$.pipe(\r\n tap({\r\n subscribe: () => {\r\n /* Incrementa per il loader */\r\n if (isLoaderActive) {\r\n updateIsLoading(ref, 1);\r\n }\r\n\r\n /* Creazione reference */\r\n add(ref, new URL(url), refType);\r\n },\r\n unsubscribe: () => {\r\n /* Disattivazione loader per sicurezza se il flusso si interrompe prima della risposta */\r\n if (isLoaderActive) {\r\n updateIsLoading(ref, -1);\r\n isLoaderActive = false;\r\n }\r\n\r\n /* Rimozione reference */\r\n remove(ref);\r\n },\r\n next: (res) => {\r\n /* Mostra toast (se presente) */\r\n if (toast) {\r\n UniToastManager.showHttp(toast, res);\r\n }\r\n },\r\n }),\r\n catchError((error) => {\r\n // Aggiorna la ref nella map\r\n updateHasError(ref, true);\r\n\r\n /* Gestione errore */\r\n return errorHandler(ref, error, PollingErrorMode.STOP);\r\n }),\r\n finalize(() => {\r\n /* Decrementa per il loader */\r\n if (isLoaderActive) {\r\n updateIsLoading(ref, -1);\r\n isLoaderActive = false;\r\n }\r\n }),\r\n );\r\n });\r\n}\r\n\r\n/**\r\n * Avvia e coordina un ciclo di polling a intervalli regolari.\r\n * Gestisce la concorrenza tramite operatori RxJS configurabili, la rimozione dei popup, di errore nelle iterazioni successive e i comportamenti custom al primo avvio.\r\n */\r\nexport function httpPolling$<T>(\r\n url: string,\r\n config: HttpConfigPolling<T>,\r\n promiseFactory: () => Promise<T>,\r\n): Observable<T> {\r\n /* Recupero configurazione */\r\n const {\r\n interval,\r\n ref,\r\n operator = MapOperator.SWITCH_MAP,\r\n errorMode = PollingErrorMode.STOP,\r\n emitValueMode = EmitValueMode.ON_NEW_DATA,\r\n firstIteration,\r\n } = config;\r\n\r\n const timer$ = timer(0, interval);\r\n const source$ = timer$.pipe(\r\n tap({\r\n subscribe: () => {\r\n /* Creazione reference */\r\n add(ref, new URL(url), 'polling');\r\n },\r\n unsubscribe: () => {\r\n /* Rimozione reference */\r\n remove(ref);\r\n },\r\n }),\r\n operatorHandler<T>(operator)((index) => {\r\n // Il loader è attivo solo al primo giro se non è esplicitamente false\r\n let isLoaderActive = index === 0 && firstIteration?.hasLoader !== false;\r\n\r\n /* Incrementa per il loader */\r\n if (isLoaderActive) {\r\n updateIsLoading(ref, 1);\r\n }\r\n\r\n return defer(() => {\r\n const http$ = from(promiseFactory());\r\n return http$.pipe(\r\n tap({\r\n unsubscribe: () => {\r\n /* Disattivazione loader per sicurezza se il flusso si interrompe prima della risposta */\r\n if (isLoaderActive) {\r\n updateIsLoading(ref, -1);\r\n isLoaderActive = false;\r\n }\r\n },\r\n next: (res) => {\r\n /* Prima risposta */\r\n if (index === 0) {\r\n /* Prima risposta: callback */\r\n if (firstIteration?.callback) {\r\n firstIteration.callback(res);\r\n }\r\n\r\n /* Prima risposta: loader */\r\n if (isLoaderActive) {\r\n updateIsLoading(ref, -1);\r\n isLoaderActive = false;\r\n }\r\n\r\n /* Prima risposta: toast */\r\n if (firstIteration?.toast) {\r\n UniToastManager.showHttp(firstIteration.toast, res);\r\n }\r\n }\r\n\r\n /* Meccanismo di ripristino automatico: se il polling torna in salute, cancella l'errore dallo store e nasconde i relativi messaggi a schermo */\r\n if (errorMode === PollingErrorMode.IGNORE_WITH_ERROR) {\r\n updateHasError(ref, false);\r\n UniErrorManager.remove(ref);\r\n }\r\n },\r\n }),\r\n catchError((error) => {\r\n /* Disattivazione loader in caso di errore al primo giro */\r\n if (isLoaderActive) {\r\n updateIsLoading(ref, -1);\r\n isLoaderActive = false;\r\n }\r\n\r\n // Aggiorna la ref nella map\r\n updateHasError(ref, true);\r\n\r\n /* Gestione errore */\r\n return errorHandler(ref, error, errorMode);\r\n }),\r\n );\r\n });\r\n }),\r\n );\r\n\r\n return emitValueMode === EmitValueMode.ON_NEW_DATA\r\n ? source$.pipe(distinctUntilChanged((prev, cur) => isEqual(prev, cur)))\r\n : source$;\r\n}\r\n\r\n/* ------------------------------------------------------------------------------- */\r\n/* ------------------------------------ Utils ------------------------------------ */\r\n/* ------------------------------------------------------------------------------- */\r\n/**\r\n * Aggiunge una nuova ref nello store solo se non è già presente.\r\n * Se l'ID esiste già, l'operazione viene interrotta per preservare il dato originale.\r\n */\r\nfunction add(id: string, url: URL, type: HttpRef['type']): void {\r\n // Recupera l'ultimo stato (Map)\r\n const oldMap = UniHttpManager.currentValue;\r\n\r\n // Controllo: se è presente l'item allora termina\r\n if (oldMap.get(id)) return;\r\n\r\n // Crea il nuovo oggetto\r\n const newItemMap: HttpRef = {\r\n type,\r\n lineId: undefined,\r\n url,\r\n hasError: false,\r\n pendingCount: 0,\r\n };\r\n\r\n // Crea una nuova istanza della Map\r\n const newMap = new Map(oldMap);\r\n newMap.set(id, newItemMap);\r\n\r\n // Aggiorna il nuovo stato notificando l'observer\r\n UniHttpManager.store.next(newMap);\r\n}\r\n\r\n/**\r\n * Rimuove un http ref tramite ID\r\n */\r\nfunction remove(id: string): void {\r\n // Recupera l'ultimo stato (Map)\r\n const oldMap = UniHttpManager.currentValue;\r\n\r\n // Controllo: se non è presente l'item allora termina\r\n if (!oldMap.has(id)) return;\r\n\r\n // Aggiorna store\r\n const newMap = new Map(oldMap);\r\n newMap.delete(id);\r\n UniHttpManager.store.next(newMap);\r\n}\r\n\r\n/**\r\n * Aggiorna il contatore delle chiamate pendenti per una specifica ref.\r\n * Incrementa o decrementa 'pendingCount' garantendo che non scenda mai sotto lo zero.\r\n * Se la ref non esiste, l'operazione viene ignorata.\r\n */\r\nfunction updateIsLoading(id: string, delta: -1 | 1): void {\r\n // Recupera l'ultimo stato (Map)\r\n const oldMap = UniHttpManager.currentValue;\r\n\r\n // Controllo: se non è presente l'item allora termina\r\n const oldItem = oldMap.get(id);\r\n if (!oldItem) return;\r\n\r\n // Aggiorna l'oggetto\r\n const newItemMap: HttpRef = {\r\n ...oldItem,\r\n pendingCount: Math.max(0, oldItem.pendingCount + delta),\r\n };\r\n\r\n // Crea una nuova istanza della Map\r\n const newMap = new Map(oldMap);\r\n newMap.set(id, newItemMap);\r\n\r\n // Aggiorna il nuovo stato notificando l'observer\r\n UniHttpManager.store.next(newMap);\r\n}\r\n\r\n/**\r\n * Aggiorna lo stato di errore per una specifica ref.\r\n * Se il valore di 'hasError' è identico a quello attuale o se la ref non esiste,\r\n * l'operazione viene interrotta per evitare aggiornamenti inutili.\r\n */\r\nfunction updateHasError(id: string, hasError: boolean): void {\r\n // Recupera l'ultimo stato (Map)\r\n const oldMap = UniHttpManager.currentValue;\r\n\r\n // Controllo: se non è presente l'item allora termina\r\n const oldItem = oldMap.get(id);\r\n if (!oldItem) return;\r\n\r\n // Controllo: se con lo stesso valore, salta\r\n if (oldItem.hasError === hasError) return;\r\n\r\n // Aggiorna l'oggetto\r\n const newItemMap: HttpRef = { ...oldItem, hasError };\r\n\r\n // Crea una nuova istanza della Map\r\n const newMap = new Map(oldMap);\r\n newMap.set(id, newItemMap);\r\n\r\n // Aggiorna il nuovo stato notificando l'observer\r\n UniHttpManager.store.next(newMap);\r\n}\r\n","/* eslint-disable unicorn/no-declarations-before-early-exit */\r\nimport { isErrorResponse, UniHttpError } from 'uni-error/http';\r\nimport type { ErrorResponse, FileDatasource } from 'uni-model-type/type';\r\n\r\n// =============================================================================\r\n// MOTORE DI ESECUZIONE HTTP\r\n// =============================================================================\r\n/**\r\n * Esegue una richiesta HTTP nativa gestendo l'imbuto dei 4 casi d'errore.\r\n */\r\nasync function execute(request: Request): Promise<Response> {\r\n const startTime = performance.now();\r\n const requestClone = request.clone();\r\n\r\n try {\r\n /* Esecuzione della richiesta HTTP nativa */\r\n const res = await fetch(request);\r\n\r\n /* Calcolo durata */\r\n const durationMs = Math.round(performance.now() - startTime);\r\n\r\n /* Gestione ok HTTP: chiamata andata a buon fine. Viene restituita la risposta al chiamante. */\r\n if (res.ok) {\r\n return res;\r\n }\r\n\r\n /* Gestione Errore HTTP: la chiamata è arrivata al server ma ha restituito uno stato 4xx o 5xx */\r\n let httpError: unknown;\r\n\r\n try {\r\n /* Clonazione della risposta per l'ispezione del payload senza consumare lo stream originale */\r\n const resClone = res.clone();\r\n\r\n /* Verifica se il formato è un JSON */\r\n const contentType = res.headers.get('content-type') ?? '';\r\n const isJson = contentType.startsWith('application/json');\r\n\r\n /* Estrazione del corpo dell'errore in base al formato rilevato */\r\n httpError = isJson ? await resClone.json() : await resClone.text();\r\n } catch {\r\n /* Fallback in caso di fallimento della clonazione o del parsing del testo */\r\n httpError = `Failed to parse error response body (Status: ${res.status})`;\r\n }\r\n\r\n // ERRORE CON STATUS, CASO A: errore applicativo backend ('be')\r\n // Se il payload estratto supera il controllo 'isHttpException', significa che la richiesta è stata elaborata dal codice C#, ha intercettato il GlobalExceptionHandler ed è ritornata come JSON strutturato.\r\n // Questo scenario si applica a qualsiasi codice (400, 404, 500, ecc.) purché sia formattato dal backend.\r\n if (isErrorResponse(httpError)) {\r\n const errorResponse = httpError;\r\n throw new UniHttpError({\r\n type: 'be',\r\n request: requestClone,\r\n httpStatus: res.status,\r\n durationMs,\r\n userAgent: navigator.userAgent,\r\n error: errorResponse,\r\n });\r\n }\r\n\r\n // ERRORE CON STATUS, CASO B: errore infrastrutturale del server ('server')\r\n // Se l'esecuzione raggiunge questo punto, il server ha risposto con un errore (es. 404, 405, 502, 504) ma non ha restituito il JSON customizzato.\r\n // Rappresenta il blocco da parte del server web (IIS, Nginx, Proxy) che ha rifiutato la chiamata o ha risposto con una pagina HTML/Testo standard.\r\n // Di conseguenza, il flag 'isBe' deve essere impostato a false poiché non deriva dalla logica applicativa.\r\n const defaultMessage = `HTTP Error ${res.status}${res.statusText ? ` (${res.statusText})` : ''}`;\r\n const errorTracker = new Error(defaultMessage);\r\n const rawError = typeof httpError === 'string' ? httpError.trim() : '';\r\n let finalMessage: string;\r\n if (rawError) {\r\n // Estrazione della prima riga per l'analisi del tipo di errore\r\n const firstLine = rawError.split('\\n', 1)[0];\r\n const exceptionRegex = /^([a-zA-Z0-9.]+\\.Exception):/i;\r\n\r\n // Verifica se la riga segue il formato standard .NET o un pattern di eccezione custom\r\n if (\r\n exceptionRegex.test(firstLine) ||\r\n firstLine.startsWith('System.') ||\r\n firstLine.startsWith('Microsoft.')\r\n ) {\r\n const colonIndex = firstLine.indexOf(': ');\r\n finalMessage = colonIndex === -1 ? firstLine : firstLine.slice(colonIndex + 2);\r\n }\r\n // Priorità: Mantenimento dell'intero corpo per errori HTML o testo generico\r\n else {\r\n finalMessage = rawError;\r\n }\r\n }\r\n // Utilizzo del messaggio di default in assenza di corpo nell'errore\r\n else {\r\n finalMessage = defaultMessage;\r\n }\r\n const errorResponse: ErrorResponse = {\r\n exception: {\r\n isBe: false,\r\n type: 'ServerError',\r\n message: finalMessage,\r\n stackTrace: errorTracker.stack ?? '',\r\n },\r\n innerException: null,\r\n };\r\n throw new UniHttpError({\r\n type: 'server',\r\n request: requestClone,\r\n httpStatus: res.status,\r\n durationMs,\r\n userAgent: navigator.userAgent,\r\n error: errorResponse,\r\n });\r\n } catch (error: unknown) {\r\n // ERRORE CON/SENZA STATUS: già gestito, rilancio diretto.\r\n // Se l'errore è un'istanza di UniHttpError (lanciata nei blocchi superiori per 'be' o 'server'), significa che è già stata catalogata correttamente.\r\n // Viene eseguito il rilancio diretto.\r\n if (error instanceof UniHttpError) {\r\n throw error;\r\n }\r\n\r\n // ERRORE SENZA STATUS, CASO A: errore di rete locale ('network')\r\n // Si verifica solo se la fetch() fallisce prima di stabilire un contatto con il server.\r\n // Il browser solleva un 'TypeError' (es. \"Failed to fetch\").\r\n if (error instanceof TypeError) {\r\n const fallbackException: ErrorResponse = {\r\n exception: {\r\n isBe: false,\r\n type: error.name || 'NetworkError',\r\n message: error.message,\r\n stackTrace: error.stack ?? '',\r\n },\r\n innerException: null,\r\n };\r\n throw new UniHttpError({\r\n type: 'network',\r\n request: requestClone,\r\n httpStatus: 0,\r\n durationMs: 0,\r\n userAgent: navigator.userAgent,\r\n error: fallbackException,\r\n });\r\n }\r\n\r\n // ERRORE SENZA STATUS, CASO B: errore frontend ('fe')\r\n // Qualsiasi altro errore imprevisto che non derivi da un fallimento della fetch o della risposta.\r\n throw error;\r\n }\r\n}\r\n\r\n// =============================================================================\r\n// API PUBBLICHE: GESTIONE DATI E FILE\r\n// =============================================================================\r\nexport async function executeHttp(request: Request): Promise<void>;\r\nexport async function executeHttp<T>(request: Request): Promise<T>;\r\nexport async function executeHttp<T>(request: Request): Promise<T | void> {\r\n /* Esegue la chiamata HTTP */\r\n const res = await execute(request);\r\n\r\n /* Gestione dello stato 204: chiamata andata a buon fine ma senza dati di ritorno */\r\n if (res.status === 204) return;\r\n\r\n /* Estrae il contenuto come testo */\r\n const text = await res.text();\r\n\r\n /* Controllo: se il testo è vuoto ('') lancia errore */\r\n if (!text || text.trim().length === 0) {\r\n throw response204Error(request, res);\r\n }\r\n\r\n /* Parsa manualmente il testo, dato che lo stream è stato già letto */\r\n return JSON.parse(text) as T;\r\n}\r\n\r\nexport async function executeBlob(request: Request): Promise<FileDatasource> {\r\n /* Esegue la chiamata HTTP */\r\n const res = await execute(request);\r\n\r\n /* Gestione dello stato 204: se la chiamata andata a buon fine ma senza dati di ritorno lancia errore */\r\n if (res.status === 204) {\r\n throw response204Error(request, res);\r\n }\r\n\r\n /* Estrae il contenuto come Blob direttamente */\r\n const blob = await res.blob();\r\n\r\n /* Controllo: se il blob è vuoto (0 byte) lancia errore */\r\n if (blob.size === 0) {\r\n throw response204Error(request, res);\r\n }\r\n\r\n /* Estrae il nome del file dall'header */\r\n const disposition = res.headers.get('Content-Disposition');\r\n let name = '';\r\n if (disposition) {\r\n const matches = /filename[^;=\\n]*=((['\"]).*?\\2|[^;\\n]*)/.exec(disposition);\r\n if (!!matches && matches[1]) {\r\n name = matches[1].replaceAll(/['\"]/g, '');\r\n }\r\n }\r\n\r\n return { blob, name };\r\n}\r\n\r\n// export async function executeFile(request: Request, dispositionType: string): Promise<void> {\r\n// const url: URL = new URL(request.url);\r\n\r\n// const authHeader = request.headers.get('Authorization');\r\n// if (authHeader && authHeader.startsWith('Bearer ')) {\r\n// const token = authHeader.slice(7);\r\n// url.searchParams.append('token', token); // Il backend dovrà accettare il token anche da query string\r\n// }\r\n\r\n// if (dispositionType === 'inline') {\r\n// UniFileManager.openPreviewInNewTab(url);\r\n// } else {\r\n// UniFileManager.download(url);\r\n// }\r\n// }\r\n\r\n// =============================================================================\r\n// HELPERS\r\n// =============================================================================\r\nfunction response204Error(request: Request, res: Response): UniHttpError {\r\n return new UniHttpError({\r\n type: 'be',\r\n request,\r\n httpStatus: res.status,\r\n durationMs: 0,\r\n userAgent: navigator.userAgent,\r\n error: {\r\n exception: {\r\n isBe: true,\r\n type: 'ProtocolError',\r\n message: 'Expected payload of type T, but received empty response.',\r\n stackTrace: '',\r\n },\r\n innerException: null,\r\n },\r\n });\r\n}\r\n","/* eslint-disable unicorn/no-break-in-nested-loop */\r\nimport { UniTypeDateManager } from 'uni-manager/type';\r\nimport type { HttpBody, HttpConfig } from 'uni-model-type/type';\r\n\r\n// =============================================================================\r\n// REQUEST\r\n// =============================================================================\r\n/**\r\n * Costruisce un oggetto Request completo e standardizzato per l'API partendo dai parametri di configurazione.\r\n * Gestisce la composizione dell'URL, la formattazione delle date nei query parametri e il merge dell'init.\r\n */\r\nexport function getRequest<T>(\r\n hostname: string,\r\n port: number,\r\n config: HttpConfig<T>,\r\n defaultRequestInit: RequestInit,\r\n): Request {\r\n const { queryParams, path, hasApiPrefix } = config;\r\n\r\n // Rimuove eventuali barre iniziali o finali dal path per evitare doppi slash (es. //api//)\r\n const cleanPath = path.replaceAll(/^\\/+|\\/+$/g, '');\r\n\r\n // Inserisce il prefisso 'api' a meno che non sia esplicitamente disabilitato nel config\r\n const segments = [hasApiPrefix === false ? '' : 'api', cleanPath].filter(Boolean);\r\n const pathFixed = '/' + segments.join('/');\r\n\r\n // Generazione dell'oggetto URL nativo combinando la base (host+porta) e il path strutturato\r\n const url = new URL(pathFixed, `http://${hostname}:${port}`);\r\n\r\n // Aggiunta query params\r\n if (queryParams) {\r\n // Regex per intercettare stringhe in formato ISO string\r\n const isoDateRegex = /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})?)?$/;\r\n\r\n for (const [key, rawValue] of Object.entries(queryParams)) {\r\n if (rawValue === undefined || rawValue === null) {\r\n continue;\r\n }\r\n\r\n // Conversione in array per usare un solo ciclo\r\n const valuesArray = Array.isArray(rawValue) ? rawValue : [rawValue];\r\n\r\n for (const item of valuesArray) {\r\n if (item === undefined || item === null) {\r\n continue;\r\n }\r\n\r\n let formattedValue: string;\r\n\r\n // Caso: Date in formato nativo -> Convertito in YYYY-MM-DD\r\n if (item instanceof Date) {\r\n formattedValue = UniTypeDateManager.toYYYYMMDD(item);\r\n }\r\n // Caso: Date in formato ISO string -> Parsato e convertito in YYYY-MM-DD\r\n else if (typeof item === 'string' && isoDateRegex.test(item)) {\r\n const parsedDate = new Date(item);\r\n // Se la stringa superava la regex ma la data non è valida -> fallback sulla stringa originale\r\n formattedValue = Number.isNaN(parsedDate.getTime())\r\n ? item\r\n : UniTypeDateManager.toYYYYMMDD(parsedDate);\r\n }\r\n // Caso: Default (Numeri, Booleani, Stringhe standard) -> Conversione a stringa pulita\r\n else {\r\n formattedValue = String(item);\r\n }\r\n\r\n // Appende il parametro formattato nell'URL\r\n url.searchParams.append(key, formattedValue);\r\n }\r\n }\r\n }\r\n\r\n // Unisce le configurazioni base registrate nel config dell'endpoint con quelle puntuali della singola chiamata\r\n const initCustom: RequestInit = {\r\n ...defaultRequestInit,\r\n ...config.init,\r\n };\r\n\r\n // Ritorna l'oggetto Request completo di URL formattato e init con tutte le proprietà standard del browser\r\n return new Request(url, initCustom);\r\n}\r\n\r\n// =============================================================================\r\n// BODY\r\n// =============================================================================\r\n/**\r\n * Controlla che le chiavi degli oggetti nel body rispettino i tipi attesi:\r\n * - Se terminano con 'timestamp' -> il valore deve essere number\r\n * - Se terminano con 'date' o 'at' -> il valore deve essere un oggetto Date\r\n * - Se iniziano con 'is', 'has', 'should', 'can' -> il valore deve essere boolean\r\n * - Se terminano/corrispondono a 'id', 'count', 'qty', 'total' -> il valore deve essere number\r\n */\r\nexport function validateHttpBody<T>(body: HttpBody<T>): void {\r\n // Gestione degli array: validazione ricorsiva di ciascun elemento\r\n if (Array.isArray(body)) {\r\n for (const item of body) {\r\n validateHttpBody(item);\r\n }\r\n return;\r\n }\r\n\r\n // Gestione degli oggetti\r\n if (body !== null && typeof body === 'object' && !(body instanceof Date)) {\r\n for (const [key, value] of Object.entries(body)) {\r\n // 1. Booleani\r\n const booleanRegEx = /^(is|has|should|can)[A-Z]/;\r\n if (booleanRegEx.test(key) && typeof value !== 'boolean') {\r\n if (value === null) return;\r\n\r\n throw new TypeError(`Validation failed: key \"${key}\" must be a boolean.`);\r\n }\r\n\r\n // 2. Stringhe\r\n if (\r\n (key.endsWith('Code') ||\r\n key.endsWith('Name') ||\r\n key.endsWith('Description') ||\r\n key.endsWith('Url')) &&\r\n typeof value !== 'string'\r\n ) {\r\n if (value === null) return;\r\n\r\n throw new TypeError(`Validation failed: key \"${key}\" must be a string.`);\r\n }\r\n\r\n // 3. Controllo Date\r\n if (key.endsWith('Date') || key.endsWith('At')) {\r\n const isDateInstance = value instanceof Date && !Number.isNaN(value.getTime());\r\n const isoRegex = /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?(Z|[+-]\\d{2}:\\d{2})?)?$/;\r\n const isDateString =\r\n typeof value === 'string' && isoRegex.test(value) && !Number.isNaN(Date.parse(value));\r\n if (!isDateInstance && !isDateString) {\r\n if (value === null) return;\r\n\r\n throw new TypeError(\r\n `Validation failed: key \"${key}\" must be a valid Date object or ISO string.`,\r\n );\r\n }\r\n }\r\n\r\n // 4. Timestamp\r\n if (key.endsWith('Timestamp')) {\r\n if (value === null) return;\r\n\r\n if (typeof value !== 'number') {\r\n throw new TypeError(`Validation failed: key \"${key}\" must be a number.`);\r\n }\r\n\r\n const date = new Date(value);\r\n if (value !== null && Number.isNaN(date.getTime())) {\r\n throw new TypeError(`Validation failed: key \"${key}\" is not a valid timestamp.`);\r\n }\r\n }\r\n\r\n // 5. Controllo Numerico\r\n const numericSuffixes = ['id', 'Id', 'ID', 'Count', 'Qty', 'Total'];\r\n if (numericSuffixes.some((suffix) => key.endsWith(suffix)) && typeof value !== 'number') {\r\n if (value === null) return;\r\n\r\n throw new TypeError(`Validation failed: key \"${key}\" must be a number.`);\r\n }\r\n\r\n // Analisi ricorsiva per la verifica di eventuali sotto-oggetti o sotto-array\r\n validateHttpBody(value);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Normalizza i valori del body così da sistemare le incongruenze tra ui e db\r\n * - Applica il trim alle stringhe\r\n * - Converte gli oggetti Date in stringhe YYYY-MM-DD\r\n * - Rimuove la proprietà 'id' se presente al livello principale (root).\r\n */\r\nexport function normalizeHttpBody<T>(\r\n body: HttpBody<T>,\r\n method: 'post' | 'put',\r\n hasToKeepId: boolean | undefined,\r\n): unknown {\r\n // Validazione iniziale\r\n validateHttpBody(body);\r\n\r\n // UNDEFINED\r\n // Tipi gestiti: undefined\r\n if (body === undefined) {\r\n return undefined;\r\n }\r\n\r\n // NULL\r\n // Tipi gestiti: null\r\n if (body === null) {\r\n return null;\r\n }\r\n\r\n // DATE\r\n // Tipi gestiti: Date\r\n const isDateInstance = body instanceof Date;\r\n const isDateString =\r\n typeof body === 'string' && /^\\d{4}-\\d{2}-\\d{2}/.test(body) && !Number.isNaN(Date.parse(body));\r\n if (isDateInstance || isDateString) {\r\n return UniTypeDateManager.toYYYYMMDD(body);\r\n }\r\n\r\n // PRIMITIVI GENERICI\r\n // Tipi gestiti: number, boolean, symbol, bigint, string\r\n if (typeof body !== 'object') {\r\n if (typeof body !== 'string') return body ?? null;\r\n\r\n // Rimuove spazi inutili e restituisce null in caso di stringa vuota\r\n return body.trim() || null;\r\n }\r\n\r\n // STRUTTURE DATI ITERABILI\r\n // Tipi gestiti: Array (qualsiasi array, es. string[], number[], Object[])\r\n // Se è un array, viene mappato ricorsivamente ogni singolo elemento al suo interno (passando isRoot = false perché gli elementi dell'array non sono l'oggetto root principale)\r\n if (Array.isArray(body)) {\r\n return body.map((item) => normalizeHttpBody(item, method, true));\r\n }\r\n\r\n // OGGETTI\r\n // Tipi gestiti: Record<string, any>, generici oggetti JavaScript ({ })\r\n // Rimozione della chiave 'id' al primo livello (root) e prosegue ricorsivamente\r\n const entries = Object.entries(body)\r\n .filter(([key]) => !(method === 'post' && !hasToKeepId && key.toLowerCase() === 'id'))\r\n .map(([key, value]) => [key, normalizeHttpBody(value, method, true)]);\r\n\r\n // Ricostruzione dell'oggetto normalizzato\r\n return Object.fromEntries(entries);\r\n}\r\n","/* eslint-disable unicorn/consistent-class-member-order */\r\nimport { BehaviorSubject, Observable, distinctUntilChanged, map, of, tap } from 'rxjs';\r\nimport { UniToastManager } from 'uni-manager/toast';\r\nimport type {\r\n FileDatasource,\r\n HttpBody,\r\n HttpBodyPrimitive,\r\n HttpConfig,\r\n HttpConfigPolling,\r\n HttpRef,\r\n ToastConfig,\r\n} from 'uni-model-type/type';\r\n\r\nimport { http$, httpPolling$ } from './core';\r\nimport { executeBlob, executeHttp } from './execute';\r\nimport { getRequest, normalizeHttpBody } from './utilities';\r\n\r\nconst CONFIG_TOAST_DEFAULT: ToastConfig = {\r\n type: 'success',\r\n label: 'OperationCompleted',\r\n};\r\n\r\nexport class UniHttpManager {\r\n /* ------------------------------------------------------------------------------- */\r\n /* ----------------------------------- Config ------------------------------------ */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Hostname del server (es. 'api.example.com' o 'localhost') */\r\n private static hostname: string;\r\n\r\n /** Porta del server su cui effettuare le chiamate (es. 80, 443 o 3000) */\r\n private static port: number;\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* --------------------------------- Metodi: get --------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Restituisce se lo store ha chiamate in attesa di risposta o meno */\r\n public static get hasWaitingRequests$(): Observable<boolean> {\r\n return this.store$.pipe(\r\n map((requestMap) => {\r\n for (const x of requestMap.values()) {\r\n if (x.pendingCount > 0) return true;\r\n }\r\n return false;\r\n }),\r\n distinctUntilChanged(),\r\n );\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* ------------------------------------ Store ------------------------------------ */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Store privato (Subject) */\r\n public static store = new BehaviorSubject<Map<string, HttpRef>>(new Map());\r\n\r\n /** Store pubblico (Observable) */\r\n public static store$: Observable<Map<string, HttpRef>> = this.store.asObservable();\r\n\r\n /** Ottiene lo stato attuale della Map senza dover sottoscrivere l'observable */\r\n public static get currentValue(): Map<string, HttpRef> {\r\n return this.store.getValue();\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: setup -------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Inizializza la configurazione di rete del manager.\r\n * Deve essere chiamato prima di effettuare qualsiasi richiesta HTTP.\r\n */\r\n public static setup(hostname: string, port: number): void {\r\n this.hostname = hostname;\r\n this.port = port;\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: CRUD --------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /*\r\n * Esegue una singola richiesta HTTP GET.\r\n * Utilizza il path configurato per costruire l'URL completo e restituisce un Observable del risultato.\r\n */\r\n public static read$(config: HttpConfig<void>): Observable<void>;\r\n public static read$<T>(config: HttpConfig<T>): Observable<T>;\r\n public static read$<T>(config: HttpConfig<void | T>): Observable<void | T> {\r\n /* Config */\r\n const defaultRequestInit: RequestInit = {\r\n method: 'GET',\r\n };\r\n const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n\r\n /* API */\r\n return http$(request.url, 'one', config, () => executeHttp<T>(request)).pipe(\r\n tap((res) => {\r\n if (config.hasToast === false || !!config.toast) return;\r\n\r\n if (!res) {\r\n UniToastManager.show({ label: 'NoItemFound' });\r\n } else if (Array.isArray(res)) {\r\n UniToastManager.show({ label: 'ItemsFound', params: { count: res.length } });\r\n }\r\n }),\r\n );\r\n }\r\n\r\n /**\r\n * Esegue una richiesta HTTP POST inviando un payload JSON nel corpo della richiesta.\r\n * Imposta automaticamente l'header 'Content-Type' come 'application/json'.\r\n */\r\n public static create$<TBody extends HttpBodyPrimitive>(\r\n config: HttpConfig<void> & { hasToKeepId?: boolean },\r\n body: HttpBody<TBody>,\r\n ): Observable<void>;\r\n public static create$<TResponse, TBody extends HttpBodyPrimitive>(\r\n config: HttpConfig<TResponse> & { hasToKeepId?: boolean },\r\n body: HttpBody<TBody>,\r\n ): Observable<TResponse>;\r\n public static create$<TResponse, TBody extends HttpBodyPrimitive>(\r\n config: HttpConfig<void | TResponse> & { hasToKeepId?: boolean },\r\n body: HttpBody<TBody>,\r\n ): Observable<void | TResponse> {\r\n /* Config */\r\n const defaultRequestInit: RequestInit = {\r\n ...config.init,\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...config.init?.headers,\r\n },\r\n body: JSON.stringify(normalizeHttpBody(body, 'post', config.hasToKeepId)),\r\n };\r\n const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n\r\n /* Config custom (toast di default) */\r\n const configCustom: HttpConfig<TResponse> = {\r\n ...config,\r\n toast: config.hasToast === false ? undefined : { ...CONFIG_TOAST_DEFAULT, ...config.toast },\r\n };\r\n\r\n /* API */\r\n return http$(request.url, 'one', configCustom, () => executeHttp<TResponse>(request));\r\n }\r\n\r\n /**\r\n * Esegue una singola richiesta HTTP PUT per aggiornare una risorsa esistente.\r\n */\r\n public static update$(config: HttpConfig<void>): Observable<void>;\r\n public static update$<TResponse>(config: HttpConfig<TResponse>): Observable<TResponse>;\r\n public static update$<TBody extends HttpBodyPrimitive>(\r\n config: HttpConfig<void>,\r\n body: HttpBody<TBody>,\r\n ): Observable<void>;\r\n public static update$<TResponse, TBody extends HttpBodyPrimitive>(\r\n config: HttpConfig<TResponse>,\r\n body: HttpBody<TBody>,\r\n ): Observable<TResponse>;\r\n public static update$<TResponse, TBody extends HttpBodyPrimitive>(\r\n config: HttpConfig<void | TResponse>,\r\n body?: HttpBody<TBody>,\r\n ): Observable<void | TResponse> {\r\n /* Config */\r\n const defaultRequestInit: RequestInit = { method: 'PUT' };\r\n if (body !== undefined) {\r\n defaultRequestInit.headers = {\r\n 'Content-Type': 'application/json',\r\n ...config.init?.headers,\r\n };\r\n defaultRequestInit.body = JSON.stringify(normalizeHttpBody(body, 'put', false));\r\n }\r\n const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n\r\n /* Config custom (toast di default) */\r\n const configCustom: HttpConfig<TResponse> = {\r\n ...config,\r\n toast: config.hasToast === false ? undefined : { ...CONFIG_TOAST_DEFAULT, ...config.toast },\r\n };\r\n\r\n /* API */\r\n return http$(request.url, 'one', configCustom, () => executeHttp<TResponse>(request));\r\n }\r\n\r\n /**\r\n * Esegue una richiesta HTTP DELETE per rimuovere una risorsa.\r\n * Utilizza il path configurato per costruire l'URL completo e restituisce un Observable del risultato.\r\n */\r\n public static delete$(config: HttpConfig<void>): Observable<void>;\r\n public static delete$<T>(config: HttpConfig<T>): Observable<T>;\r\n public static delete$<T>(config: HttpConfig<void | T>): Observable<void | T> {\r\n /* Config */\r\n const defaultRequestInit: RequestInit = {\r\n method: 'DELETE',\r\n };\r\n const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n\r\n /* Config custom (toast di default) */\r\n const configCustom: HttpConfig<T> = {\r\n ...config,\r\n toast: config.hasToast === false ? undefined : { ...CONFIG_TOAST_DEFAULT, ...config.toast },\r\n };\r\n\r\n /* API */\r\n return http$(request.url, 'one', configCustom, () => executeHttp<T>(request));\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------- Metodi: CRUD file/image ---------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n // /**\r\n // * Recupera un'immagine tramite una richiesta GET e la trasforma in un formato gestibile (es. Blob o Base64).\r\n // * Delega la logica di conversione alla funzione executeImage.\r\n // */\r\n // public static readImage$(config: HttpConfig<FileDatasource>): Observable<void | FileDatasource> {\r\n // /* Config */\r\n // const defaultRequestInit: RequestInit = {\r\n // method: 'GET',\r\n // };\r\n // const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n // /* API */\r\n // return http$(request.url, 'image', config, () => executeBlob(request));\r\n // }\r\n\r\n /**\r\n * Recupera un file (es. PDF) tramite una richiesta GET e restituisce un Object URL temporaneo.\r\n * Delega la logica di conversione alla funzione executeFile.\r\n */\r\n public static readFile$(\r\n config: HttpConfig<void> & { queryParams: { dispositionType: 'inline' } },\r\n ): Observable<URL>;\r\n public static readFile$(\r\n config: HttpConfig<void> & { queryParams: { dispositionType: 'attachment' } },\r\n ): Observable<FileDatasource>;\r\n public static readFile$(\r\n config: HttpConfig<void> & { queryParams: { dispositionType: 'inline' | 'attachment' } },\r\n ): Observable<URL | FileDatasource>;\r\n public static readFile$(\r\n config: HttpConfig<void> & { queryParams: { dispositionType: 'inline' | 'attachment' } },\r\n ): Observable<URL | FileDatasource> {\r\n /* Config */\r\n const defaultRequestInit: RequestInit = {\r\n method: 'GET',\r\n };\r\n const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n\r\n // Se è inline, restituisce l'URL arricchito con il token (senza fare la fetch)\r\n if (config.queryParams.dispositionType === 'inline') {\r\n const url: URL = new URL(request.url);\r\n\r\n /* Header */\r\n const authHeader = request.headers.get('Authorization');\r\n if (authHeader && authHeader.startsWith('Bearer ')) {\r\n const token = authHeader.slice(7);\r\n url.searchParams.append('token', token);\r\n }\r\n\r\n return of(url);\r\n }\r\n\r\n // Se è attachment, esegue la chiamata HTTP e restituisce il Blob binario\r\n return http$(request.url, 'image', config, () => executeBlob(request));\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* ---------------------------- Metodi: CRUD polling ----------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Avvia un ciclo di polling basato su richieste GET.\r\n * Continua a emettere valori in base alla configurazione di intervallo definita in HttpConfigPolling.\r\n */\r\n public static readPolling$(config: HttpConfigPolling<void>): Observable<void>;\r\n public static readPolling$<T>(config: HttpConfigPolling<T>): Observable<T>;\r\n public static readPolling$<T>(config: HttpConfigPolling<void | T>): Observable<void | T> {\r\n /* Config */\r\n const defaultRequestInit: RequestInit = {\r\n method: 'GET',\r\n };\r\n const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n\r\n /* API */\r\n return httpPolling$(request.url, config, () => executeHttp<T>(request));\r\n }\r\n\r\n /**\r\n * Avvia un ciclo di polling basato su richieste POST.\r\n * Invia il body specificato a ogni iterazione del ciclo.\r\n */\r\n public static createPolling$<TBody extends HttpBodyPrimitive>(\r\n config: HttpConfigPolling<void> & { hasToKeepId?: boolean },\r\n body: HttpBody<TBody>,\r\n ): Observable<void>;\r\n public static createPolling$<TResponse, TBody extends HttpBodyPrimitive>(\r\n config: HttpConfigPolling<TResponse> & { hasToKeepId?: boolean },\r\n body: HttpBody<TBody>,\r\n ): Observable<TResponse>;\r\n public static createPolling$<TResponse, TBody extends HttpBodyPrimitive>(\r\n config: HttpConfigPolling<void | TResponse> & { hasToKeepId?: boolean },\r\n body: HttpBody<TBody>,\r\n ): Observable<void | TResponse> {\r\n /* Config */\r\n const defaultRequestInit: RequestInit = {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify(normalizeHttpBody(body, 'post', config.hasToKeepId)),\r\n };\r\n const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n\r\n /* API */\r\n return httpPolling$(request.url, config, () => executeHttp<TResponse>(request));\r\n }\r\n\r\n /**\r\n * Avvia un ciclo di polling basato su richieste PUT.\r\n */\r\n public static updatePolling$(config: HttpConfigPolling<void>): Observable<void>;\r\n public static updatePolling$<TBody extends HttpBodyPrimitive>(\r\n config: HttpConfigPolling<void>,\r\n body: HttpBody<TBody>,\r\n ): Observable<void>;\r\n public static updatePolling$<TResponse>(\r\n config: HttpConfigPolling<TResponse>,\r\n ): Observable<TResponse>;\r\n public static updatePolling$<TResponse, TBody extends HttpBodyPrimitive>(\r\n config: HttpConfigPolling<TResponse>,\r\n body: HttpBody<TBody>,\r\n ): Observable<TResponse>;\r\n public static updatePolling$<TResponse, TBody extends HttpBodyPrimitive>(\r\n config: HttpConfigPolling<void | TResponse>,\r\n body?: HttpBody<TBody>,\r\n ): Observable<void | TResponse> {\r\n /* Config */\r\n const defaultRequestInit: RequestInit = {\r\n method: 'PUT',\r\n };\r\n if (body !== undefined) {\r\n defaultRequestInit.headers = {\r\n 'Content-Type': 'application/json',\r\n ...config.init?.headers,\r\n };\r\n defaultRequestInit.body = JSON.stringify(normalizeHttpBody(body, 'put', false));\r\n }\r\n const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n\r\n /* API */\r\n return httpPolling$(request.url, config, () => executeHttp<TResponse>(request));\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"uni-manager-http.mjs","sources":["../../../projects/uni-manager/http/handler.ts","../../../projects/uni-manager/http/core.ts","../../../projects/uni-manager/http/execute.ts","../../../projects/uni-manager/http/utilities.ts","../../../projects/uni-manager/http/manager.ts","../../../projects/uni-manager/http/uni-manager-http.ts"],"sourcesContent":["import {\r\n EMPTY,\r\n Observable,\r\n OperatorFunction,\r\n concatMap,\r\n exhaustMap,\r\n mergeMap,\r\n of,\r\n switchMap,\r\n throwError,\r\n} from 'rxjs';\r\nimport { UniHttpError } from 'uni-error/http';\r\nimport { UniErrorManager } from 'uni-manager/error';\r\nimport { MapOperator, PollingErrorMode } from 'uni-model-type/enum';\r\n\r\nexport function operatorHandler<T>(\r\n operator: MapOperator,\r\n): (project: (value: number) => Observable<T>) => OperatorFunction<number, T> {\r\n // Gestione della concorrenza in base al parametro\r\n switch (operator) {\r\n case MapOperator.EXHAUST_MAP: {\r\n return (project) => exhaustMap(project);\r\n }\r\n case MapOperator.CONCAT_MAP: {\r\n return (project) => concatMap(project);\r\n }\r\n case MapOperator.MERGE_MAP: {\r\n return (project) => mergeMap(project);\r\n }\r\n case MapOperator.SWITCH_MAP: {\r\n return (project) => switchMap(project);\r\n }\r\n }\r\n}\r\n\r\nexport function errorHandler(\r\n ref: string,\r\n error: unknown,\r\n errorMode: PollingErrorMode,\r\n): Observable<never> {\r\n // Controllo: sia effettivamente un errore di tipo 'UniHttpError'\r\n if (error instanceof UniHttpError) {\r\n switch (errorMode) {\r\n case PollingErrorMode.IGNORE: {\r\n return of();\r\n }\r\n case PollingErrorMode.SKIP: {\r\n return EMPTY;\r\n }\r\n case PollingErrorMode.IGNORE_WITH_ERROR: {\r\n UniErrorManager.add(ref, error);\r\n return of();\r\n }\r\n case PollingErrorMode.STOP: {\r\n UniErrorManager.add(ref, error);\r\n return throwError(() => error);\r\n }\r\n }\r\n } else {\r\n return throwError(() => error);\r\n }\r\n}\r\n","/* eslint-disable unicorn/prefer-early-return */\r\nimport isEqual from 'lodash-es/isEqual';\r\nimport {\r\n Observable,\r\n catchError,\r\n defer,\r\n distinctUntilChanged,\r\n finalize,\r\n from,\r\n tap,\r\n timer,\r\n} from 'rxjs';\r\nimport { UniErrorManager } from 'uni-manager/error';\r\nimport { UniToastManager } from 'uni-manager/toast';\r\nimport { EmitValueMode, MapOperator, PollingErrorMode } from 'uni-model-type/enum';\r\nimport type { HttpConfig, HttpConfigPolling, HttpRef } from 'uni-model-type/type';\r\n\r\nimport { errorHandler, operatorHandler } from './handler';\r\nimport { UniHttpManager } from './manager';\r\n\r\n/* ------------------------------------------------------------------------------- */\r\n/* -------------------------------- Funzioni Core RxJS -------------------------- */\r\n/* ------------------------------------------------------------------------------- */\r\n/**\r\n * Gestisce l'esecuzione e il ciclo di vita di una singola richiesta HTTP.\r\n * Si occupa della registrazione della reference, della gestione dei loader, dei toast di successo e dell'intercettazione degli errori.\r\n */\r\nexport function http$<T>(\r\n url: string,\r\n refType: HttpRef['type'],\r\n config: HttpConfig<T>,\r\n promiseCallback: () => Promise<T>,\r\n): Observable<T> {\r\n /* Recupero configurazione */\r\n const { ref, toast, hasLoader } = config;\r\n\r\n // Usiamo un flag let per garantire che il loader venga spento una sola volta\r\n let isLoaderActive = hasLoader !== false;\r\n\r\n return defer(() => {\r\n const http$ = from(promiseCallback());\r\n return http$.pipe(\r\n tap({\r\n subscribe: () => {\r\n /* Creazione reference */\r\n UniHttpManager.add(ref, new URL(url), refType);\r\n\r\n /* Incrementa per il loader */\r\n if (isLoaderActive) {\r\n UniHttpManager.updateIsLoading(ref, 1);\r\n }\r\n },\r\n unsubscribe: () => {\r\n /* Disattivazione loader per sicurezza se il flusso si interrompe prima della risposta */\r\n if (isLoaderActive) {\r\n UniHttpManager.updateIsLoading(ref, -1);\r\n isLoaderActive = false;\r\n }\r\n\r\n /* Rimozione reference */\r\n UniHttpManager.remove(ref);\r\n },\r\n next: (res) => {\r\n /* Mostra toast (se presente) */\r\n if (toast) {\r\n UniToastManager.showHttp(toast, res);\r\n }\r\n },\r\n }),\r\n catchError((error) => {\r\n // Aggiorna la ref nella map\r\n UniHttpManager.updateHasError(ref, true);\r\n\r\n /* Gestione errore */\r\n return errorHandler(ref, error, PollingErrorMode.STOP);\r\n }),\r\n finalize(() => {\r\n /* Decrementa per il loader */\r\n if (isLoaderActive) {\r\n UniHttpManager.updateIsLoading(ref, -1);\r\n isLoaderActive = false;\r\n }\r\n }),\r\n );\r\n });\r\n}\r\n\r\n/**\r\n * Avvia e coordina un ciclo di polling a intervalli regolari.\r\n * Gestisce la concorrenza tramite operatori RxJS configurabili, la rimozione dei popup, di errore nelle iterazioni successive e i comportamenti custom al primo avvio.\r\n */\r\nexport function httpPolling$<T>(\r\n url: string,\r\n config: HttpConfigPolling<T>,\r\n promiseFactory: () => Promise<T>,\r\n): Observable<T> {\r\n /* Recupero configurazione */\r\n const {\r\n interval,\r\n ref,\r\n operator = MapOperator.SWITCH_MAP,\r\n errorMode = PollingErrorMode.STOP,\r\n emitValueMode = EmitValueMode.ON_NEW_DATA,\r\n firstIteration,\r\n } = config;\r\n\r\n const timer$ = timer(0, interval);\r\n const source$ = timer$.pipe(\r\n tap({\r\n subscribe: () => {\r\n /* Creazione reference */\r\n UniHttpManager.add(ref, new URL(url), 'polling');\r\n },\r\n unsubscribe: () => {\r\n /* Rimozione reference */\r\n UniHttpManager.remove(ref);\r\n },\r\n }),\r\n operatorHandler<T>(operator)((index) => {\r\n // Il loader è attivo solo al primo giro se non è esplicitamente false\r\n let isLoaderActive = index === 0 && firstIteration?.hasLoader !== false;\r\n\r\n /* Incrementa per il loader */\r\n if (isLoaderActive) {\r\n UniHttpManager.updateIsLoading(ref, 1);\r\n }\r\n\r\n return defer(() => {\r\n const http$ = from(promiseFactory());\r\n return http$.pipe(\r\n tap({\r\n unsubscribe: () => {\r\n /* Disattivazione loader per sicurezza se il flusso si interrompe prima della risposta */\r\n if (isLoaderActive) {\r\n UniHttpManager.updateIsLoading(ref, -1);\r\n isLoaderActive = false;\r\n }\r\n },\r\n next: (res) => {\r\n /* Prima risposta */\r\n if (index === 0) {\r\n /* Prima risposta: callback */\r\n if (firstIteration?.callback) {\r\n firstIteration.callback(res);\r\n }\r\n\r\n /* Prima risposta: loader */\r\n if (isLoaderActive) {\r\n UniHttpManager.updateIsLoading(ref, -1);\r\n isLoaderActive = false;\r\n }\r\n\r\n /* Prima risposta: toast */\r\n if (firstIteration?.toast) {\r\n UniToastManager.showHttp(firstIteration.toast, res);\r\n }\r\n }\r\n\r\n /* Meccanismo di ripristino automatico: se il polling torna in salute, cancella l'errore dallo store e nasconde i relativi messaggi a schermo */\r\n if (errorMode === PollingErrorMode.IGNORE_WITH_ERROR) {\r\n UniHttpManager.updateHasError(ref, false);\r\n UniErrorManager.remove(ref);\r\n }\r\n },\r\n }),\r\n catchError((error) => {\r\n /* Disattivazione loader in caso di errore al primo giro */\r\n if (isLoaderActive) {\r\n UniHttpManager.updateIsLoading(ref, -1);\r\n isLoaderActive = false;\r\n }\r\n\r\n // Aggiorna la ref nella map\r\n UniHttpManager.updateHasError(ref, true);\r\n\r\n /* Gestione errore */\r\n return errorHandler(ref, error, errorMode);\r\n }),\r\n );\r\n });\r\n }),\r\n );\r\n\r\n return emitValueMode === EmitValueMode.ON_NEW_DATA\r\n ? source$.pipe(distinctUntilChanged((prev, cur) => isEqual(prev, cur)))\r\n : source$;\r\n}\r\n","/* eslint-disable unicorn/no-declarations-before-early-exit */\r\nimport { isErrorResponse, UniHttpError } from 'uni-error/http';\r\nimport type { ErrorResponse, FileDatasource } from 'uni-model-type/type';\r\n\r\n// =============================================================================\r\n// API PUBBLICHE: GESTIONE DATI E FILE\r\n// =============================================================================\r\nexport async function executeHttp(request: Request): Promise<void>;\r\nexport async function executeHttp<T>(request: Request): Promise<T>;\r\nexport async function executeHttp<T>(request: Request): Promise<T | void> {\r\n /* Esegue la chiamata HTTP */\r\n const res = await execute(request);\r\n\r\n /* Gestione dello stato 204: chiamata andata a buon fine ma senza dati di ritorno */\r\n if (res.status === 204) return;\r\n\r\n /* Estrae il contenuto come testo */\r\n const text = await res.text();\r\n\r\n /* Controllo: se il testo è vuoto ('') lancia errore */\r\n if (!text || text.trim().length === 0) {\r\n throw response204Error(request, res);\r\n }\r\n\r\n /* Parsa manualmente il testo, dato che lo stream è stato già letto */\r\n return JSON.parse(text) as T;\r\n}\r\n\r\nexport async function executeBlob(request: Request): Promise<FileDatasource> {\r\n /* Esegue la chiamata HTTP */\r\n const res = await execute(request);\r\n\r\n /* Gestione dello stato 204: se la chiamata andata a buon fine ma senza dati di ritorno lancia errore */\r\n if (res.status === 204) {\r\n throw response204Error(request, res);\r\n }\r\n\r\n /* Estrae il contenuto come Blob direttamente */\r\n const blob = await res.blob();\r\n\r\n /* Controllo: se il blob è vuoto (0 byte) lancia errore */\r\n if (blob.size === 0) {\r\n throw response204Error(request, res);\r\n }\r\n\r\n /* Estrae il nome del file dall'header */\r\n const disposition = res.headers.get('Content-Disposition');\r\n let name = '';\r\n if (disposition) {\r\n const matches = /filename[^;=\\n]*=((['\"]).*?\\2|[^;\\n]*)/.exec(disposition);\r\n if (!!matches && matches[1]) {\r\n name = matches[1].replaceAll(/['\"]/g, '');\r\n }\r\n }\r\n\r\n return { blob, name };\r\n}\r\n\r\n// =============================================================================\r\n// HELPERS\r\n// =============================================================================\r\n/**\r\n * Esegue una richiesta HTTP nativa gestendo l'imbuto dei 4 casi d'errore.\r\n */\r\nasync function execute(request: Request): Promise<Response> {\r\n const startTime = performance.now();\r\n const requestClone = request.clone();\r\n\r\n try {\r\n /* Esecuzione della richiesta HTTP nativa */\r\n const res = await fetch(request);\r\n\r\n /* Calcolo durata */\r\n const durationMs = Math.round(performance.now() - startTime);\r\n\r\n /* Gestione ok HTTP: chiamata andata a buon fine. Viene restituita la risposta al chiamante. */\r\n if (res.ok) {\r\n return res;\r\n }\r\n\r\n /* Gestione Errore HTTP: la chiamata è arrivata al server ma ha restituito uno stato 4xx o 5xx */\r\n let httpError: unknown;\r\n\r\n try {\r\n /* Clonazione della risposta per l'ispezione del payload senza consumare lo stream originale */\r\n const resClone = res.clone();\r\n\r\n /* Verifica se il formato è un JSON */\r\n const contentType = res.headers.get('content-type') ?? '';\r\n const isJson = contentType.startsWith('application/json');\r\n\r\n /* Estrazione del corpo dell'errore in base al formato rilevato */\r\n httpError = isJson ? await resClone.json() : await resClone.text();\r\n } catch {\r\n /* Fallback in caso di fallimento della clonazione o del parsing del testo */\r\n httpError = `Failed to parse error response body (Status: ${res.status})`;\r\n }\r\n\r\n // ERRORE CON STATUS, CASO A: errore applicativo backend ('be')\r\n // Se il payload estratto supera il controllo 'isHttpException', significa che la richiesta è stata elaborata dal codice C#, ha intercettato il GlobalExceptionHandler ed è ritornata come JSON strutturato.\r\n // Questo scenario si applica a qualsiasi codice (400, 404, 500, ecc.) purché sia formattato dal backend.\r\n if (isErrorResponse(httpError)) {\r\n const errorResponse = httpError;\r\n throw new UniHttpError({\r\n type: 'be',\r\n request: requestClone,\r\n httpStatus: res.status,\r\n durationMs,\r\n userAgent: navigator.userAgent,\r\n error: errorResponse,\r\n });\r\n }\r\n\r\n // ERRORE CON STATUS, CASO B: errore infrastrutturale del server ('server')\r\n // Se l'esecuzione raggiunge questo punto, il server ha risposto con un errore (es. 404, 405, 502, 504) ma non ha restituito il JSON customizzato.\r\n // Rappresenta il blocco da parte del server web (IIS, Nginx, Proxy) che ha rifiutato la chiamata o ha risposto con una pagina HTML/Testo standard.\r\n // Di conseguenza, il flag 'isBe' deve essere impostato a false poiché non deriva dalla logica applicativa.\r\n const defaultMessage = `HTTP Error ${res.status}${res.statusText ? ` (${res.statusText})` : ''}`;\r\n const errorTracker = new Error(defaultMessage);\r\n const rawError = typeof httpError === 'string' ? httpError.trim() : '';\r\n let finalMessage: string;\r\n if (rawError) {\r\n // Estrazione della prima riga per l'analisi del tipo di errore\r\n const firstLine = rawError.split('\\n', 1)[0];\r\n const exceptionRegex = /^([a-zA-Z0-9.]+\\.Exception):/i;\r\n\r\n // Verifica se la riga segue il formato standard .NET o un pattern di eccezione custom\r\n if (\r\n exceptionRegex.test(firstLine) ||\r\n firstLine.startsWith('System.') ||\r\n firstLine.startsWith('Microsoft.')\r\n ) {\r\n const colonIndex = firstLine.indexOf(': ');\r\n finalMessage = colonIndex === -1 ? firstLine : firstLine.slice(colonIndex + 2);\r\n }\r\n // Priorità: Mantenimento dell'intero corpo per errori HTML o testo generico\r\n else {\r\n finalMessage = rawError;\r\n }\r\n }\r\n // Utilizzo del messaggio di default in assenza di corpo nell'errore\r\n else {\r\n finalMessage = defaultMessage;\r\n }\r\n const errorResponse: ErrorResponse = {\r\n exception: {\r\n isBe: false,\r\n type: 'ServerError',\r\n message: finalMessage,\r\n stackTrace: errorTracker.stack ?? '',\r\n },\r\n innerException: null,\r\n };\r\n throw new UniHttpError({\r\n type: 'server',\r\n request: requestClone,\r\n httpStatus: res.status,\r\n durationMs,\r\n userAgent: navigator.userAgent,\r\n error: errorResponse,\r\n });\r\n } catch (error: unknown) {\r\n // ERRORE CON/SENZA STATUS: già gestito, rilancio diretto.\r\n // Se l'errore è un'istanza di UniHttpError (lanciata nei blocchi superiori per 'be' o 'server'), significa che è già stata catalogata correttamente.\r\n // Viene eseguito il rilancio diretto.\r\n if (error instanceof UniHttpError) {\r\n throw error;\r\n }\r\n\r\n // ERRORE SENZA STATUS, CASO A: errore di rete locale ('network')\r\n // Si verifica solo se la fetch() fallisce prima di stabilire un contatto con il server.\r\n // Il browser solleva un 'TypeError' (es. \"Failed to fetch\").\r\n if (error instanceof TypeError) {\r\n const fallbackException: ErrorResponse = {\r\n exception: {\r\n isBe: false,\r\n type: error.name || 'NetworkError',\r\n message: error.message,\r\n stackTrace: error.stack ?? '',\r\n },\r\n innerException: null,\r\n };\r\n throw new UniHttpError({\r\n type: 'network',\r\n request: requestClone,\r\n httpStatus: 0,\r\n durationMs: 0,\r\n userAgent: navigator.userAgent,\r\n error: fallbackException,\r\n });\r\n }\r\n\r\n // ERRORE SENZA STATUS, CASO B: errore frontend ('fe')\r\n // Qualsiasi altro errore imprevisto che non derivi da un fallimento della fetch o della risposta.\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Gestione errore in caso di assenza di risposta quando invece era prevista\r\n */\r\nfunction response204Error(request: Request, res: Response): UniHttpError {\r\n return new UniHttpError({\r\n type: 'be',\r\n request,\r\n httpStatus: res.status,\r\n durationMs: 0,\r\n userAgent: navigator.userAgent,\r\n error: {\r\n exception: {\r\n isBe: true,\r\n type: 'ProtocolError',\r\n message: 'Expected payload of type T, but received empty response.',\r\n stackTrace: '',\r\n },\r\n innerException: null,\r\n },\r\n });\r\n}\r\n","/* eslint-disable unicorn/no-break-in-nested-loop */\r\nimport { UniTypeDateManager } from 'uni-manager/type';\r\nimport type { HttpBody, HttpConfig } from 'uni-model-type/type';\r\n\r\n// =============================================================================\r\n// REQUEST\r\n// =============================================================================\r\n/**\r\n * Costruisce un oggetto Request completo e standardizzato per l'API partendo dai parametri di configurazione.\r\n * Gestisce la composizione dell'URL, la formattazione delle date nei query parametri e il merge dell'init.\r\n */\r\nexport function getRequest<T>(\r\n hostname: string,\r\n port: number,\r\n config: HttpConfig<T>,\r\n defaultRequestInit: RequestInit,\r\n): Request {\r\n const { queryParams, path, hasApiPrefix } = config;\r\n\r\n // Rimuove eventuali barre iniziali o finali dal path per evitare doppi slash (es. //api//)\r\n const cleanPath = path.replaceAll(/^\\/+|\\/+$/g, '');\r\n\r\n // Inserisce il prefisso 'api' a meno che non sia esplicitamente disabilitato nel config\r\n const segments = [hasApiPrefix === false ? '' : 'api', cleanPath].filter(Boolean);\r\n const pathFixed = '/' + segments.join('/');\r\n\r\n // Generazione dell'oggetto URL nativo combinando la base (host+porta) e il path strutturato\r\n const url = new URL(pathFixed, `http://${hostname}:${port}`);\r\n\r\n // Aggiunta query params\r\n if (queryParams) {\r\n // Regex per intercettare stringhe in formato ISO string\r\n const isoDateRegex = /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})?)?$/;\r\n\r\n for (const [key, rawValue] of Object.entries(queryParams)) {\r\n if (rawValue === undefined || rawValue === null) {\r\n continue;\r\n }\r\n\r\n // Conversione in array per usare un solo ciclo\r\n const valuesArray = Array.isArray(rawValue) ? rawValue : [rawValue];\r\n\r\n for (const item of valuesArray) {\r\n if (item === undefined || item === null) {\r\n continue;\r\n }\r\n\r\n let formattedValue: string;\r\n\r\n // Caso: Date in formato nativo -> Convertito in YYYY-MM-DD\r\n if (item instanceof Date) {\r\n formattedValue = UniTypeDateManager.toYYYYMMDD(item);\r\n }\r\n // Caso: Date in formato ISO string -> Parsato e convertito in YYYY-MM-DD\r\n else if (typeof item === 'string' && isoDateRegex.test(item)) {\r\n const parsedDate = new Date(item);\r\n // Se la stringa superava la regex ma la data non è valida -> fallback sulla stringa originale\r\n formattedValue = Number.isNaN(parsedDate.getTime())\r\n ? item\r\n : UniTypeDateManager.toYYYYMMDD(parsedDate);\r\n }\r\n // Caso: Default (Numeri, Booleani, Stringhe standard) -> Conversione a stringa pulita\r\n else {\r\n formattedValue = String(item);\r\n }\r\n\r\n // Appende il parametro formattato nell'URL\r\n url.searchParams.append(key, formattedValue);\r\n }\r\n }\r\n }\r\n\r\n // Unisce le configurazioni base registrate nel config dell'endpoint con quelle puntuali della singola chiamata\r\n const initCustom: RequestInit = {\r\n ...defaultRequestInit,\r\n ...config.init,\r\n };\r\n\r\n // Ritorna l'oggetto Request completo di URL formattato e init con tutte le proprietà standard del browser\r\n return new Request(url, initCustom);\r\n}\r\n\r\n// =============================================================================\r\n// BODY\r\n// =============================================================================\r\n/**\r\n * Controlla che le chiavi degli oggetti nel body rispettino i tipi attesi:\r\n * - Se terminano con 'timestamp' -> il valore deve essere number\r\n * - Se terminano con 'date' o 'at' -> il valore deve essere un oggetto Date\r\n * - Se iniziano con 'is', 'has', 'should', 'can' -> il valore deve essere boolean\r\n * - Se terminano/corrispondono a 'id', 'count', 'qty', 'total' -> il valore deve essere number\r\n */\r\nexport function validateHttpBody<T>(body: HttpBody<T>): void {\r\n // Gestione degli array: validazione ricorsiva di ciascun elemento\r\n if (Array.isArray(body)) {\r\n for (const item of body) {\r\n validateHttpBody(item);\r\n }\r\n return;\r\n }\r\n\r\n // Gestione degli oggetti\r\n if (body !== null && typeof body === 'object' && !(body instanceof Date)) {\r\n for (const [key, value] of Object.entries(body)) {\r\n // 1. Booleani\r\n const booleanRegEx = /^(is|has|should|can)[A-Z]/;\r\n if (booleanRegEx.test(key) && typeof value !== 'boolean') {\r\n if (value === null) return;\r\n\r\n throw new TypeError(`Validation failed: key \"${key}\" must be a boolean.`);\r\n }\r\n\r\n // 2. Stringhe\r\n if (\r\n (key.endsWith('Code') ||\r\n key.endsWith('Name') ||\r\n key.endsWith('Description') ||\r\n key.endsWith('Url')) &&\r\n typeof value !== 'string'\r\n ) {\r\n if (value === null) return;\r\n\r\n throw new TypeError(`Validation failed: key \"${key}\" must be a string.`);\r\n }\r\n\r\n // 3. Controllo Date\r\n if (key.endsWith('Date') || key.endsWith('At')) {\r\n const isDateInstance = value instanceof Date && !Number.isNaN(value.getTime());\r\n const isoRegex = /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?(Z|[+-]\\d{2}:\\d{2})?)?$/;\r\n const isDateString =\r\n typeof value === 'string' && isoRegex.test(value) && !Number.isNaN(Date.parse(value));\r\n if (!isDateInstance && !isDateString) {\r\n if (value === null) return;\r\n\r\n throw new TypeError(\r\n `Validation failed: key \"${key}\" must be a valid Date object or ISO string.`,\r\n );\r\n }\r\n }\r\n\r\n // 4. Timestamp\r\n if (key.endsWith('Timestamp')) {\r\n if (value === null) return;\r\n\r\n if (typeof value !== 'number') {\r\n throw new TypeError(`Validation failed: key \"${key}\" must be a number.`);\r\n }\r\n\r\n const date = new Date(value);\r\n if (value !== null && Number.isNaN(date.getTime())) {\r\n throw new TypeError(`Validation failed: key \"${key}\" is not a valid timestamp.`);\r\n }\r\n }\r\n\r\n // 5. Controllo Numerico\r\n const numericSuffixes = ['id', 'Id', 'ID', 'Count', 'Qty', 'Total'];\r\n if (numericSuffixes.some((suffix) => key.endsWith(suffix)) && typeof value !== 'number') {\r\n if (value === null) return;\r\n\r\n throw new TypeError(`Validation failed: key \"${key}\" must be a number.`);\r\n }\r\n\r\n // Analisi ricorsiva per la verifica di eventuali sotto-oggetti o sotto-array\r\n validateHttpBody(value);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Normalizza i valori del body così da sistemare le incongruenze tra ui e db\r\n * - Applica il trim alle stringhe\r\n * - Converte gli oggetti Date in stringhe YYYY-MM-DD\r\n * - Rimuove la proprietà 'id' se presente al livello principale (root).\r\n */\r\nexport function normalizeHttpBody<T>(\r\n body: HttpBody<T>,\r\n method: 'post' | 'put',\r\n hasToKeepId: boolean | undefined,\r\n): unknown {\r\n // Validazione iniziale\r\n validateHttpBody(body);\r\n\r\n // UNDEFINED\r\n // Tipi gestiti: undefined\r\n if (body === undefined) {\r\n return undefined;\r\n }\r\n\r\n // NULL\r\n // Tipi gestiti: null\r\n if (body === null) {\r\n return null;\r\n }\r\n\r\n // DATE\r\n // Tipi gestiti: Date\r\n const isDateInstance = body instanceof Date;\r\n const isDateString =\r\n typeof body === 'string' && /^\\d{4}-\\d{2}-\\d{2}/.test(body) && !Number.isNaN(Date.parse(body));\r\n if (isDateInstance || isDateString) {\r\n return UniTypeDateManager.toYYYYMMDD(body);\r\n }\r\n\r\n // PRIMITIVI GENERICI\r\n // Tipi gestiti: number, boolean, symbol, bigint, string\r\n if (typeof body !== 'object') {\r\n if (typeof body !== 'string') return body ?? null;\r\n\r\n // Rimuove spazi inutili e restituisce null in caso di stringa vuota\r\n return body.trim() || null;\r\n }\r\n\r\n // STRUTTURE DATI ITERABILI\r\n // Tipi gestiti: Array (qualsiasi array, es. string[], number[], Object[])\r\n // Se è un array, viene mappato ricorsivamente ogni singolo elemento al suo interno (passando isRoot = false perché gli elementi dell'array non sono l'oggetto root principale)\r\n if (Array.isArray(body)) {\r\n return body.map((item) => normalizeHttpBody(item, method, true));\r\n }\r\n\r\n // OGGETTI\r\n // Tipi gestiti: Record<string, any>, generici oggetti JavaScript ({ })\r\n // Rimozione della chiave 'id' al primo livello (root) e prosegue ricorsivamente\r\n const entries = Object.entries(body)\r\n .filter(([key]) => !(method === 'post' && !hasToKeepId && key.toLowerCase() === 'id'))\r\n .map(([key, value]) => [key, normalizeHttpBody(value, method, true)]);\r\n\r\n // Ricostruzione dell'oggetto normalizzato\r\n return Object.fromEntries(entries);\r\n}\r\n","/* eslint-disable unicorn/prefer-iterator-to-array */\r\n/* eslint-disable unicorn/prefer-iterator-helpers */\r\nimport { BehaviorSubject, Observable, distinctUntilChanged, map, of, tap } from 'rxjs';\r\nimport { UniToastManager } from 'uni-manager/toast';\r\nimport type {\r\n FileDatasource,\r\n HttpBody,\r\n HttpBodyPrimitive,\r\n HttpConfig,\r\n HttpConfigPolling,\r\n HttpRef,\r\n ToastConfig,\r\n} from 'uni-model-type/type';\r\n\r\nimport { http$, httpPolling$ } from './core';\r\nimport { executeBlob, executeHttp } from './execute';\r\nimport { getRequest, normalizeHttpBody } from './utilities';\r\n\r\nconst CONFIG_TOAST_DEFAULT: ToastConfig = {\r\n type: 'success',\r\n label: 'OperationCompleted',\r\n};\r\n\r\nexport class UniHttpManager {\r\n /* ------------------------------------------------------------------------------- */\r\n /* ----------------------------------- Config ------------------------------------ */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Hostname del server (es. 'api.example.com' o 'localhost') */\r\n private static hostname: string;\r\n\r\n /** Porta del server su cui effettuare le chiamate (es. 80, 443 o 3000) */\r\n private static port: number;\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* ------------------------------------ Store ------------------------------------ */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Store privato (Subject) */\r\n public static store = new BehaviorSubject<Map<string, HttpRef>>(new Map());\r\n\r\n /** Store pubblico (Observable) */\r\n public static store$: Observable<Map<string, HttpRef>> = this.store.asObservable();\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* --------------------------------- Metodi: get --------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Ottiene lo stato attuale della Map senza dover sottoscrivere l'observable */\r\n public static get currentValue(): Map<string, HttpRef> {\r\n return this.store.getValue();\r\n }\r\n\r\n /** Restituisce se lo store ha chiamate in attesa di risposta o meno */\r\n public static get hasWaitingRequests$(): Observable<boolean> {\r\n return this.store$.pipe(\r\n map((requestMap) => [...requestMap.values()].some((request) => request.pendingCount > 0)),\r\n distinctUntilChanged(),\r\n );\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: setup -------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Inizializza la configurazione di rete del manager.\r\n * Deve essere chiamato prima di effettuare qualsiasi richiesta HTTP.\r\n */\r\n public static setup(hostname: string, port: number): void {\r\n this.hostname = hostname;\r\n this.port = port;\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: store -------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Aggiunge una nuova ref nello store solo se non è già presente.\r\n * Se l'ID esiste già, l'operazione viene interrotta per preservare il dato originale.\r\n */\r\n public static add(id: string, url: URL, type: HttpRef['type']): void {\r\n // Recupera l'ultimo stato (Map)\r\n const oldMap = this.currentValue;\r\n\r\n // Controllo: se è presente l'item allora termina\r\n if (oldMap.get(id)) return;\r\n\r\n // Crea il nuovo oggetto\r\n const newItemMap: HttpRef = {\r\n type,\r\n lineId: undefined,\r\n url,\r\n hasError: false,\r\n pendingCount: 0,\r\n };\r\n\r\n // Crea una nuova istanza della Map\r\n const newMap = new Map(oldMap);\r\n newMap.set(id, newItemMap);\r\n\r\n // Aggiorna il nuovo stato notificando l'observer\r\n this.store.next(newMap);\r\n }\r\n\r\n /**\r\n * Rimuove un http ref tramite ID\r\n */\r\n public static remove(id: string): void {\r\n // Recupera l'ultimo stato (Map)\r\n const oldMap = this.currentValue;\r\n\r\n // Controllo: se non è presente l'item allora termina\r\n if (!oldMap.has(id)) return;\r\n\r\n // Aggiorna store\r\n const newMap = new Map(oldMap);\r\n newMap.delete(id);\r\n this.store.next(newMap);\r\n }\r\n\r\n /**\r\n * Aggiorna il contatore delle chiamate pendenti per una specifica ref.\r\n * Incrementa o decrementa 'pendingCount' garantendo che non scenda mai sotto lo zero.\r\n * Se la ref non esiste, l'operazione viene ignorata.\r\n */\r\n public static updateIsLoading(id: string, delta: -1 | 1): void {\r\n // Recupera l'ultimo stato (Map)\r\n const oldMap = this.currentValue;\r\n\r\n // Controllo: se non è presente l'item allora termina\r\n const oldItem = oldMap.get(id);\r\n if (!oldItem) return;\r\n\r\n // Aggiorna l'oggetto\r\n const newItemMap: HttpRef = {\r\n ...oldItem,\r\n pendingCount: Math.max(0, oldItem.pendingCount + delta),\r\n };\r\n\r\n // Crea una nuova istanza della Map\r\n const newMap = new Map(oldMap);\r\n newMap.set(id, newItemMap);\r\n\r\n // Aggiorna il nuovo stato notificando l'observer\r\n this.store.next(newMap);\r\n }\r\n\r\n /**\r\n * Aggiorna lo stato di errore per una specifica ref.\r\n * Se il valore di 'hasError' è identico a quello attuale o se la ref non esiste,\r\n * l'operazione viene interrotta per evitare aggiornamenti inutili.\r\n */\r\n public static updateHasError(id: string, hasError: boolean): void {\r\n // Recupera l'ultimo stato (Map)\r\n const oldMap = this.currentValue;\r\n\r\n // Controllo: se non è presente l'item allora termina\r\n const oldItem = oldMap.get(id);\r\n if (!oldItem) return;\r\n\r\n // Controllo: se con lo stesso valore, salta\r\n if (oldItem.hasError === hasError) return;\r\n\r\n // Aggiorna l'oggetto\r\n const newItemMap: HttpRef = { ...oldItem, hasError };\r\n\r\n // Crea una nuova istanza della Map\r\n const newMap = new Map(oldMap);\r\n newMap.set(id, newItemMap);\r\n\r\n // Aggiorna il nuovo stato notificando l'observer\r\n this.store.next(newMap);\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: CRUD --------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /*\r\n * Esegue una singola richiesta HTTP GET.\r\n * Utilizza il path configurato per costruire l'URL completo e restituisce un Observable del risultato.\r\n */\r\n public static read$(config: HttpConfig<void>): Observable<void>;\r\n public static read$<T>(config: HttpConfig<T>): Observable<T>;\r\n public static read$<T>(config: HttpConfig<void | T>): Observable<void | T> {\r\n /* Config */\r\n const defaultRequestInit: RequestInit = {\r\n method: 'GET',\r\n };\r\n const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n\r\n /* API */\r\n return http$(request.url, 'one', config, () => executeHttp<T>(request)).pipe(\r\n tap((res) => {\r\n if (config.hasToast === false || !!config.toast) return;\r\n\r\n if (!res) {\r\n UniToastManager.show({ label: 'NoItemFound' });\r\n } else if (Array.isArray(res)) {\r\n UniToastManager.show({ label: 'ItemsFound', params: { count: res.length } });\r\n }\r\n }),\r\n );\r\n }\r\n\r\n /**\r\n * Esegue una richiesta HTTP POST inviando un payload JSON nel corpo della richiesta.\r\n * Imposta automaticamente l'header 'Content-Type' come 'application/json'.\r\n */\r\n public static create$<TBody extends HttpBodyPrimitive>(\r\n config: HttpConfig<void> & { hasToKeepId?: boolean },\r\n body: HttpBody<TBody>,\r\n ): Observable<void>;\r\n public static create$<TResponse, TBody extends HttpBodyPrimitive>(\r\n config: HttpConfig<TResponse> & { hasToKeepId?: boolean },\r\n body: HttpBody<TBody>,\r\n ): Observable<TResponse>;\r\n public static create$<TResponse, TBody extends HttpBodyPrimitive>(\r\n config: HttpConfig<void | TResponse> & { hasToKeepId?: boolean },\r\n body: HttpBody<TBody>,\r\n ): Observable<void | TResponse> {\r\n /* Config */\r\n const defaultRequestInit: RequestInit = {\r\n ...config.init,\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...config.init?.headers,\r\n },\r\n body: JSON.stringify(normalizeHttpBody(body, 'post', config.hasToKeepId)),\r\n };\r\n const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n\r\n /* Config custom (toast di default) */\r\n const configCustom: HttpConfig<TResponse> = {\r\n ...config,\r\n toast: config.hasToast === false ? undefined : { ...CONFIG_TOAST_DEFAULT, ...config.toast },\r\n };\r\n\r\n /* API */\r\n return http$(request.url, 'one', configCustom, () => executeHttp<TResponse>(request));\r\n }\r\n\r\n /**\r\n * Esegue una singola richiesta HTTP PUT per aggiornare una risorsa esistente.\r\n */\r\n public static update$(config: HttpConfig<void>): Observable<void>;\r\n public static update$<TResponse>(config: HttpConfig<TResponse>): Observable<TResponse>;\r\n public static update$<TBody extends HttpBodyPrimitive>(\r\n config: HttpConfig<void>,\r\n body: HttpBody<TBody>,\r\n ): Observable<void>;\r\n public static update$<TResponse, TBody extends HttpBodyPrimitive>(\r\n config: HttpConfig<TResponse>,\r\n body: HttpBody<TBody>,\r\n ): Observable<TResponse>;\r\n public static update$<TResponse, TBody extends HttpBodyPrimitive>(\r\n config: HttpConfig<void | TResponse>,\r\n body?: HttpBody<TBody>,\r\n ): Observable<void | TResponse> {\r\n /* Config */\r\n const defaultRequestInit: RequestInit = { method: 'PUT' };\r\n if (body !== undefined) {\r\n defaultRequestInit.headers = {\r\n 'Content-Type': 'application/json',\r\n ...config.init?.headers,\r\n };\r\n defaultRequestInit.body = JSON.stringify(normalizeHttpBody(body, 'put', false));\r\n }\r\n const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n\r\n /* Config custom (toast di default) */\r\n const configCustom: HttpConfig<TResponse> = {\r\n ...config,\r\n toast: config.hasToast === false ? undefined : { ...CONFIG_TOAST_DEFAULT, ...config.toast },\r\n };\r\n\r\n /* API */\r\n return http$(request.url, 'one', configCustom, () => executeHttp<TResponse>(request));\r\n }\r\n\r\n /**\r\n * Esegue una richiesta HTTP DELETE per rimuovere una risorsa.\r\n * Utilizza il path configurato per costruire l'URL completo e restituisce un Observable del risultato.\r\n */\r\n public static delete$(config: HttpConfig<void>): Observable<void>;\r\n public static delete$<T>(config: HttpConfig<T>): Observable<T>;\r\n public static delete$<T>(config: HttpConfig<void | T>): Observable<void | T> {\r\n /* Config */\r\n const defaultRequestInit: RequestInit = {\r\n method: 'DELETE',\r\n };\r\n const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n\r\n /* Config custom (toast di default) */\r\n const configCustom: HttpConfig<T> = {\r\n ...config,\r\n toast: config.hasToast === false ? undefined : { ...CONFIG_TOAST_DEFAULT, ...config.toast },\r\n };\r\n\r\n /* API */\r\n return http$(request.url, 'one', configCustom, () => executeHttp<T>(request));\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------- Metodi: CRUD file/image ---------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n // /**\r\n // * Recupera un'immagine tramite una richiesta GET e la trasforma in un formato gestibile (es. Blob o Base64).\r\n // * Delega la logica di conversione alla funzione executeImage.\r\n // */\r\n // public static readImage$(config: HttpConfig<FileDatasource>): Observable<void | FileDatasource> {\r\n // /* Config */\r\n // const defaultRequestInit: RequestInit = {\r\n // method: 'GET',\r\n // };\r\n // const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n // /* API */\r\n // return http$(request.url, 'image', config, () => executeBlob(request));\r\n // }\r\n\r\n /**\r\n * Recupera un file (es. PDF) tramite una richiesta GET e restituisce un Object URL temporaneo.\r\n * Delega la logica di conversione alla funzione executeFile.\r\n */\r\n public static readFile$(\r\n config: HttpConfig<void> & { queryParams: { dispositionType: 'inline' } },\r\n ): Observable<URL>;\r\n public static readFile$(\r\n config: HttpConfig<void> & { queryParams: { dispositionType: 'attachment' } },\r\n ): Observable<FileDatasource>;\r\n public static readFile$(\r\n config: HttpConfig<void> & { queryParams: { dispositionType: 'inline' | 'attachment' } },\r\n ): Observable<URL | FileDatasource>;\r\n public static readFile$(\r\n config: HttpConfig<void> & { queryParams: { dispositionType: 'inline' | 'attachment' } },\r\n ): Observable<URL | FileDatasource> {\r\n /* Config */\r\n const defaultRequestInit: RequestInit = {\r\n method: 'GET',\r\n };\r\n const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n\r\n // Se è inline, restituisce l'URL arricchito con il token (senza fare la fetch)\r\n if (config.queryParams.dispositionType === 'inline') {\r\n const url: URL = new URL(request.url);\r\n\r\n /* Header */\r\n const authHeader = request.headers.get('Authorization');\r\n if (authHeader && authHeader.startsWith('Bearer ')) {\r\n const token = authHeader.slice(7);\r\n url.searchParams.append('token', token);\r\n }\r\n\r\n return of(url);\r\n }\r\n\r\n // Se è attachment, esegue la chiamata HTTP e restituisce il Blob binario\r\n return http$(request.url, 'image', config, () => executeBlob(request));\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* ---------------------------- Metodi: CRUD polling ----------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Avvia un ciclo di polling basato su richieste GET.\r\n * Continua a emettere valori in base alla configurazione di intervallo definita in HttpConfigPolling.\r\n */\r\n public static readPolling$(config: HttpConfigPolling<void>): Observable<void>;\r\n public static readPolling$<T>(config: HttpConfigPolling<T>): Observable<T>;\r\n public static readPolling$<T>(config: HttpConfigPolling<void | T>): Observable<void | T> {\r\n /* Config */\r\n const defaultRequestInit: RequestInit = {\r\n method: 'GET',\r\n };\r\n const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n\r\n /* API */\r\n return httpPolling$(request.url, config, () => executeHttp<T>(request));\r\n }\r\n\r\n /**\r\n * Avvia un ciclo di polling basato su richieste POST.\r\n * Invia il body specificato a ogni iterazione del ciclo.\r\n */\r\n public static createPolling$<TBody extends HttpBodyPrimitive>(\r\n config: HttpConfigPolling<void> & { hasToKeepId?: boolean },\r\n body: HttpBody<TBody>,\r\n ): Observable<void>;\r\n public static createPolling$<TResponse, TBody extends HttpBodyPrimitive>(\r\n config: HttpConfigPolling<TResponse> & { hasToKeepId?: boolean },\r\n body: HttpBody<TBody>,\r\n ): Observable<TResponse>;\r\n public static createPolling$<TResponse, TBody extends HttpBodyPrimitive>(\r\n config: HttpConfigPolling<void | TResponse> & { hasToKeepId?: boolean },\r\n body: HttpBody<TBody>,\r\n ): Observable<void | TResponse> {\r\n /* Config */\r\n const defaultRequestInit: RequestInit = {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify(normalizeHttpBody(body, 'post', config.hasToKeepId)),\r\n };\r\n const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n\r\n /* API */\r\n return httpPolling$(request.url, config, () => executeHttp<TResponse>(request));\r\n }\r\n\r\n /**\r\n * Avvia un ciclo di polling basato su richieste PUT.\r\n */\r\n public static updatePolling$(config: HttpConfigPolling<void>): Observable<void>;\r\n public static updatePolling$<TBody extends HttpBodyPrimitive>(\r\n config: HttpConfigPolling<void>,\r\n body: HttpBody<TBody>,\r\n ): Observable<void>;\r\n public static updatePolling$<TResponse>(\r\n config: HttpConfigPolling<TResponse>,\r\n ): Observable<TResponse>;\r\n public static updatePolling$<TResponse, TBody extends HttpBodyPrimitive>(\r\n config: HttpConfigPolling<TResponse>,\r\n body: HttpBody<TBody>,\r\n ): Observable<TResponse>;\r\n public static updatePolling$<TResponse, TBody extends HttpBodyPrimitive>(\r\n config: HttpConfigPolling<void | TResponse>,\r\n body?: HttpBody<TBody>,\r\n ): Observable<void | TResponse> {\r\n /* Config */\r\n const defaultRequestInit: RequestInit = {\r\n method: 'PUT',\r\n };\r\n if (body !== undefined) {\r\n defaultRequestInit.headers = {\r\n 'Content-Type': 'application/json',\r\n ...config.init?.headers,\r\n };\r\n defaultRequestInit.body = JSON.stringify(normalizeHttpBody(body, 'put', false));\r\n }\r\n const request: Request = getRequest(this.hostname, this.port, config, defaultRequestInit);\r\n\r\n /* API */\r\n return httpPolling$(request.url, config, () => executeHttp<TResponse>(request));\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -120,7 +120,7 @@ class UniLocaleManager {
|
|
|
120
120
|
static translate(key, prefix = 'lbl', params) {
|
|
121
121
|
if (!key)
|
|
122
122
|
return '-';
|
|
123
|
-
// Costruzione chiave: prefissoGlobale + prefissoLocale +
|
|
123
|
+
// Costruzione chiave: prefissoGlobale + prefissoLocale + labelConInizialeMaiuscola
|
|
124
124
|
const keyParts = key.trim().split(/(?=[A-Z])/);
|
|
125
125
|
const rootKeyParts = keyParts.filter((p) => p.toLowerCase() !== prefix.toLowerCase());
|
|
126
126
|
const cleanKey = rootKeyParts.length > 0 ? rootKeyParts.join('') : undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uni-manager-locale.mjs","sources":["../../../projects/uni-manager/locale/utilities.ts","../../../projects/uni-manager/locale/manager.ts","../../../projects/uni-manager/locale/uni-manager-locale.ts"],"sourcesContent":["export enum Locale {\r\n EN = 'en-US',\r\n ES = 'es-CL',\r\n IT = 'it-IT',\r\n}\r\n\r\nexport function getNavigatorLanguageFormatted(navigatorLanguage: string): Locale {\r\n switch (navigatorLanguage) {\r\n case 'en': {\r\n return Locale.EN;\r\n }\r\n\r\n case 'es': {\r\n return Locale.ES;\r\n }\r\n\r\n case 'it': {\r\n return Locale.IT;\r\n }\r\n\r\n default: {\r\n return Locale.EN;\r\n }\r\n }\r\n}\r\n","/* eslint-disable unicorn/consistent-class-member-order */\r\nimport { BehaviorSubject } from 'rxjs';\r\n\r\nimport { Locale, getNavigatorLanguageFormatted } from './utilities';\r\n\r\nexport class UniLocaleManager {\r\n /* ------------------------------------------------------------------------------- */\r\n /* ----------------------------------- Config ------------------------------------ */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Codice lingua corrente (es. 'it-IT', 'en-US') usato per formattare date e numeri */\r\n private static _locale: Locale = Locale.EN;\r\n\r\n /** Elenco dei codici lingua supportati dall'applicazione (es. ['it-IT', 'en-US']) */\r\n private static _localesSupported: Locale[] = [];\r\n\r\n /** Prefisso globale applicato a tutte le chiavi di traduzione (es. 'APP_') */\r\n private static _prefix: string | undefined = undefined;\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* --------------------------------- Metodi: get --------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Restituisce il codice lingua corrente */\r\n public static get locale(): Locale {\r\n return this._locale;\r\n }\r\n\r\n /** Restituisce l'array contenente tutti i codici locale supportati.*/\r\n public static get localesSupported(): Locale[] {\r\n return this._localesSupported;\r\n }\r\n\r\n /** Restituisce solo la lingua (es. 'it') */\r\n public static get language(): string {\r\n return this._locale.split('-', 1)[0];\r\n }\r\n\r\n /** Restituisce solo il paese (es. 'IT') */\r\n public static get region(): string {\r\n const parts = this._locale.split('-');\r\n return parts.length > 1 ? parts[1] : '';\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* ------------------------------------ Store ------------------------------------ */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Store privato (Subject) */\r\n public static store = new BehaviorSubject<Record<string, string>>({});\r\n\r\n /** Store pubblico (Observable) */\r\n public static store$ = this.store.asObservable();\r\n\r\n /** Ottiene il dizionario attuale senza sottoscrizione */\r\n public static get currentValue(): Record<string, string> {\r\n return this.store.getValue();\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: setup -------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Inizializza la configurazione di rete del manager.\r\n * Deve essere chiamato prima di effettuare qualsiasi richiesta HTTP.\r\n */\r\n public static setup(options?: { prefix?: string }): void {\r\n /* Locale */\r\n const lsLocale = localStorage.getItem('uni-locale') as Locale | null;\r\n if (lsLocale && Object.values(Locale).includes(lsLocale)) {\r\n this._locale = lsLocale;\r\n } else {\r\n const navigatorLocale = navigator.language || Locale.EN;\r\n const navigatorLanguage = navigatorLocale.split('-', 1)[0].toLowerCase();\r\n this._locale = getNavigatorLanguageFormatted(navigatorLanguage);\r\n }\r\n\r\n /* Opzione prefisso */\r\n if (options?.prefix) {\r\n this._prefix = options.prefix;\r\n }\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: set -------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Imposta l'elenco dei codici lingua supportati dall'applicazione */\r\n public static setLocalesSupported(locales: string[] | undefined): void {\r\n const list = locales ?? [];\r\n\r\n // Controllo: presenza di stringhe che non appartenenti all'enum Locale\r\n const validLocales = Object.values(Locale) as string[];\r\n const invalidLocale = list.find((lang) => !validLocales.includes(lang));\r\n\r\n if (invalidLocale) {\r\n throw new Error(`Locale '${invalidLocale}' is not supported`);\r\n }\r\n\r\n // Assegnazione valori\r\n this._localesSupported = list as Locale[];\r\n }\r\n\r\n /**\r\n * Aggiorna lo store locale con il dizionario delle traduzioni fornito.\r\n * Se viene passato undefined, lo store viene inizializzato come oggetto vuoto.\r\n */\r\n public static setTranslations(translations: Record<string, string> | undefined): void {\r\n this.store.next(translations ?? {});\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* ----------------------------- Metodi: traduzioni ------------------------------ */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Traduce una label in base al dizionario caricato.\r\n * Gestisce la composizione della chiave, i parametri dinamici (interpolazione) e il fallback.\r\n */\r\n public static translate(\r\n key: string,\r\n prefix = 'lbl',\r\n params?: Record<string, string | number | Date>,\r\n ): string {\r\n if (!key) return '-';\r\n\r\n // Costruzione chiave: prefissoGlobale + prefissoLocale + LabelConInizialeMaiuscola\r\n const keyParts = key.trim().split(/(?=[A-Z])/);\r\n const rootKeyParts = keyParts.filter((p) => p.toLowerCase() !== prefix.toLowerCase());\r\n const cleanKey = rootKeyParts.length > 0 ? rootKeyParts.join('') : undefined;\r\n const capitalizedKey = cleanKey ? cleanKey.charAt(0).toUpperCase() + cleanKey.slice(1) : '';\r\n const finalKey = `${this._prefix ?? ''}${prefix}${capitalizedKey}`;\r\n\r\n // Cerca la chiave in minuscolo (standardizzazione)\r\n let translation = this.currentValue?.[finalKey.toLowerCase()];\r\n\r\n // Log e fallback se la traduzione manca\r\n if (!translation) {\r\n console.warn(`Translation missing for key: ${finalKey}`);\r\n return `🔑 ${finalKey}`;\r\n }\r\n\r\n // Interpolazione variabili\r\n if (params) {\r\n for (const [key, value] of Object.entries(params)) {\r\n const displayValue =\r\n value instanceof Date ? value.toLocaleDateString(this._locale) : String(value);\r\n\r\n translation = translation.replaceAll(`{{${key}}}`, () => displayValue);\r\n }\r\n }\r\n\r\n return translation;\r\n }\r\n\r\n /**\r\n * Traduce una stringa che contiene parametri separati da un carattere specifico.\r\n * Supporta ora un numero arbitrario di parametri in formato \"label/param1/param2\"\r\n * o semplicemente \"label\".\r\n */\r\n public static translateInlineParams(keyWithParams: string, splitChar: string): string {\r\n if (!keyWithParams) return '-';\r\n\r\n const [label, ...params] = keyWithParams.split(splitChar);\r\n\r\n // Se non ci sono parametri, esegui una traduzione semplice\r\n if (params.length === 0) {\r\n return this.translate(label);\r\n }\r\n\r\n // Mappa i parametri in un oggetto di interpolazione: { inlineParam0: val, inlineParam1: val, ... }\r\n const interpolationParameters: Record<string, string> = {};\r\n for (const [index, val] of params.entries()) {\r\n interpolationParameters[`param${index}`] = val;\r\n }\r\n\r\n return this.translate(label, 'lbl', interpolationParameters);\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* ------------------------------- Metodi: numeri -------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Converte un valore numerico in una stringa formattata secondo il locale impostato.\r\n * Disabilita i separatori delle migliaia e forza un numero fisso di decimali.\r\n */\r\n public static toStringNumber(value: number, decimal: number): string {\r\n return new Intl.NumberFormat(this._locale, {\r\n useGrouping: true,\r\n minimumFractionDigits: decimal,\r\n maximumFractionDigits: decimal,\r\n numberingSystem: 'latn',\r\n }).format(value);\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: date --------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Formatta una data o una stringa in base al locale corrente.\r\n * Gestisce tre modalità predefinite (date, time, full) e accetta opzioni personalizzate Intl.\r\n */\r\n public static toDate(\r\n date: Date | string | number,\r\n mode: 'date' | 'time' | 'full' = 'full',\r\n force?: { oldLang: string; newLocale: string },\r\n ): string {\r\n const dt = new Date(date);\r\n\r\n // Controllo: validità data\r\n if (Number.isNaN(dt.getTime())) {\r\n console.error(`[UniLocaleManager] Data non valida fornita a formatDateTime:`, date);\r\n return '';\r\n }\r\n\r\n // Controllo: locale da forzare\r\n const locale = force && this._locale.startsWith(force.oldLang) ? force.newLocale : this._locale;\r\n\r\n switch (mode) {\r\n case 'date': {\r\n return dt.toLocaleDateString(locale);\r\n }\r\n case 'time': {\r\n return dt.toLocaleTimeString(locale);\r\n }\r\n case 'full': {\r\n return dt.toLocaleString(locale);\r\n }\r\n }\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;IAAY;AAAZ,CAAA,UAAY,MAAM,EAAA;AAChB,IAAA,MAAA,CAAA,IAAA,CAAA,GAAA,OAAY;AACZ,IAAA,MAAA,CAAA,IAAA,CAAA,GAAA,OAAY;AACZ,IAAA,MAAA,CAAA,IAAA,CAAA,GAAA,OAAY;AACd,CAAC,EAJW,MAAM,KAAN,MAAM,GAAA,EAAA,CAAA,CAAA;AAMZ,SAAU,6BAA6B,CAAC,iBAAyB,EAAA;IACrE,QAAQ,iBAAiB;QACvB,KAAK,IAAI,EAAE;YACT,OAAO,MAAM,CAAC,EAAE;QAClB;QAEA,KAAK,IAAI,EAAE;YACT,OAAO,MAAM,CAAC,EAAE;QAClB;QAEA,KAAK,IAAI,EAAE;YACT,OAAO,MAAM,CAAC,EAAE;QAClB;QAEA,SAAS;YACP,OAAO,MAAM,CAAC,EAAE;QAClB;;AAEJ;;ACxBA;MAKa,gBAAgB,CAAA;;;;;AAKZ,IAAA,SAAA,IAAA,CAAA,OAAO,GAAW,MAAM,CAAC,EAAE,CAAC;;aAG5B,IAAA,CAAA,iBAAiB,GAAa,EAAE,CAAC;;aAGjC,IAAA,CAAA,OAAO,GAAuB,SAAS,CAAC;;;;;AAMhD,IAAA,WAAW,MAAM,GAAA;QACtB,OAAO,IAAI,CAAC,OAAO;IACrB;;AAGO,IAAA,WAAW,gBAAgB,GAAA;QAChC,OAAO,IAAI,CAAC,iBAAiB;IAC/B;;AAGO,IAAA,WAAW,QAAQ,GAAA;AACxB,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC;;AAGO,IAAA,WAAW,MAAM,GAAA;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;AACrC,QAAA,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE;IACzC;;;;;AAMc,IAAA,SAAA,IAAA,CAAA,KAAK,GAAG,IAAI,eAAe,CAAyB,EAAE,CAAC,CAAC;;AAGxD,IAAA,SAAA,IAAA,CAAA,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;;AAG1C,IAAA,WAAW,YAAY,GAAA;AAC5B,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE;IAC9B;;;;AAKA;;;AAGG;IACI,OAAO,KAAK,CAAC,OAA6B,EAAA;;QAE/C,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,YAAY,CAAkB;AACpE,QAAA,IAAI,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;AACxD,YAAA,IAAI,CAAC,OAAO,GAAG,QAAQ;QACzB;aAAO;YACL,MAAM,eAAe,GAAG,SAAS,CAAC,QAAQ,IAAI,MAAM,CAAC,EAAE;AACvD,YAAA,MAAM,iBAAiB,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;AACxE,YAAA,IAAI,CAAC,OAAO,GAAG,6BAA6B,CAAC,iBAAiB,CAAC;QACjE;;AAGA,QAAA,IAAI,OAAO,EAAE,MAAM,EAAE;AACnB,YAAA,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM;QAC/B;IACF;;;;;IAMO,OAAO,mBAAmB,CAAC,OAA6B,EAAA;AAC7D,QAAA,MAAM,IAAI,GAAG,OAAO,IAAI,EAAE;;QAG1B,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAa;AACtD,QAAA,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEvE,IAAI,aAAa,EAAE;AACjB,YAAA,MAAM,IAAI,KAAK,CAAC,WAAW,aAAa,CAAA,kBAAA,CAAoB,CAAC;QAC/D;;AAGA,QAAA,IAAI,CAAC,iBAAiB,GAAG,IAAgB;IAC3C;AAEA;;;AAGG;IACI,OAAO,eAAe,CAAC,YAAgD,EAAA;QAC5E,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC;IACrC;;;;AAKA;;;AAGG;IACI,OAAO,SAAS,CACrB,GAAW,EACX,MAAM,GAAG,KAAK,EACd,MAA+C,EAAA;AAE/C,QAAA,IAAI,CAAC,GAAG;AAAE,YAAA,OAAO,GAAG;;QAGpB,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC;QAC9C,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,WAAW,EAAE,CAAC;QACrF,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,SAAS;QAC5E,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE;AAC3F,QAAA,MAAM,QAAQ,GAAG,CAAA,EAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAA,EAAG,MAAM,CAAA,EAAG,cAAc,EAAE;;AAGlE,QAAA,IAAI,WAAW,GAAG,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;;QAG7D,IAAI,CAAC,WAAW,EAAE;AAChB,YAAA,OAAO,CAAC,IAAI,CAAC,gCAAgC,QAAQ,CAAA,CAAE,CAAC;YACxD,OAAO,CAAA,GAAA,EAAM,QAAQ,CAAA,CAAE;QACzB;;QAGA,IAAI,MAAM,EAAE;AACV,YAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;gBACjD,MAAM,YAAY,GAChB,KAAK,YAAY,IAAI,GAAG,KAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;AAEhF,gBAAA,WAAW,GAAG,WAAW,CAAC,UAAU,CAAC,CAAA,EAAA,EAAK,GAAG,CAAA,EAAA,CAAI,EAAE,MAAM,YAAY,CAAC;YACxE;QACF;AAEA,QAAA,OAAO,WAAW;IACpB;AAEA;;;;AAIG;AACI,IAAA,OAAO,qBAAqB,CAAC,aAAqB,EAAE,SAAiB,EAAA;AAC1E,QAAA,IAAI,CAAC,aAAa;AAAE,YAAA,OAAO,GAAG;AAE9B,QAAA,MAAM,CAAC,KAAK,EAAE,GAAG,MAAM,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC;;AAGzD,QAAA,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;AACvB,YAAA,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;QAC9B;;QAGA,MAAM,uBAAuB,GAA2B,EAAE;AAC1D,QAAA,KAAK,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE;AAC3C,YAAA,uBAAuB,CAAC,CAAA,KAAA,EAAQ,KAAK,EAAE,CAAC,GAAG,GAAG;QAChD;QAEA,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,uBAAuB,CAAC;IAC9D;;;;AAKA;;;AAGG;AACI,IAAA,OAAO,cAAc,CAAC,KAAa,EAAE,OAAe,EAAA;QACzD,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE;AACzC,YAAA,WAAW,EAAE,IAAI;AACjB,YAAA,qBAAqB,EAAE,OAAO;AAC9B,YAAA,qBAAqB,EAAE,OAAO;AAC9B,YAAA,eAAe,EAAE,MAAM;AACxB,SAAA,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;IAClB;;;;AAKA;;;AAGG;IACI,OAAO,MAAM,CAClB,IAA4B,EAC5B,IAAA,GAAiC,MAAM,EACvC,KAA8C,EAAA;AAE9C,QAAA,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC;;QAGzB,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE;AAC9B,YAAA,OAAO,CAAC,KAAK,CAAC,8DAA8D,EAAE,IAAI,CAAC;AACnF,YAAA,OAAO,EAAE;QACX;;QAGA,MAAM,MAAM,GAAG,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,OAAO;QAE/F,QAAQ,IAAI;YACV,KAAK,MAAM,EAAE;AACX,gBAAA,OAAO,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC;YACtC;YACA,KAAK,MAAM,EAAE;AACX,gBAAA,OAAO,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC;YACtC;YACA,KAAK,MAAM,EAAE;AACX,gBAAA,OAAO,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC;YAClC;;IAEJ;;;AChOF;;AAEG;;;;"}
|
|
1
|
+
{"version":3,"file":"uni-manager-locale.mjs","sources":["../../../projects/uni-manager/locale/utilities.ts","../../../projects/uni-manager/locale/manager.ts","../../../projects/uni-manager/locale/uni-manager-locale.ts"],"sourcesContent":["export enum Locale {\r\n EN = 'en-US',\r\n ES = 'es-CL',\r\n IT = 'it-IT',\r\n}\r\n\r\nexport function getNavigatorLanguageFormatted(navigatorLanguage: string): Locale {\r\n switch (navigatorLanguage) {\r\n case 'en': {\r\n return Locale.EN;\r\n }\r\n\r\n case 'es': {\r\n return Locale.ES;\r\n }\r\n\r\n case 'it': {\r\n return Locale.IT;\r\n }\r\n\r\n default: {\r\n return Locale.EN;\r\n }\r\n }\r\n}\r\n","/* eslint-disable unicorn/consistent-class-member-order */\r\nimport { BehaviorSubject } from 'rxjs';\r\n\r\nimport { Locale, getNavigatorLanguageFormatted } from './utilities';\r\n\r\nexport class UniLocaleManager {\r\n /* ------------------------------------------------------------------------------- */\r\n /* ----------------------------------- Config ------------------------------------ */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Codice lingua corrente (es. 'it-IT', 'en-US') usato per formattare date e numeri */\r\n private static _locale: Locale = Locale.EN;\r\n\r\n /** Elenco dei codici lingua supportati dall'applicazione (es. ['it-IT', 'en-US']) */\r\n private static _localesSupported: Locale[] = [];\r\n\r\n /** Prefisso globale applicato a tutte le chiavi di traduzione (es. 'APP_') */\r\n private static _prefix: string | undefined = undefined;\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* --------------------------------- Metodi: get --------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Restituisce il codice lingua corrente */\r\n public static get locale(): Locale {\r\n return this._locale;\r\n }\r\n\r\n /** Restituisce l'array contenente tutti i codici locale supportati.*/\r\n public static get localesSupported(): Locale[] {\r\n return this._localesSupported;\r\n }\r\n\r\n /** Restituisce solo la lingua (es. 'it') */\r\n public static get language(): string {\r\n return this._locale.split('-', 1)[0];\r\n }\r\n\r\n /** Restituisce solo il paese (es. 'IT') */\r\n public static get region(): string {\r\n const parts = this._locale.split('-');\r\n return parts.length > 1 ? parts[1] : '';\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* ------------------------------------ Store ------------------------------------ */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Store privato (Subject) */\r\n public static store = new BehaviorSubject<Record<string, string>>({});\r\n\r\n /** Store pubblico (Observable) */\r\n public static store$ = this.store.asObservable();\r\n\r\n /** Ottiene il dizionario attuale senza sottoscrizione */\r\n public static get currentValue(): Record<string, string> {\r\n return this.store.getValue();\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: setup -------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Inizializza la configurazione di rete del manager.\r\n * Deve essere chiamato prima di effettuare qualsiasi richiesta HTTP.\r\n */\r\n public static setup(options?: { prefix?: string }): void {\r\n /* Locale */\r\n const lsLocale = localStorage.getItem('uni-locale') as Locale | null;\r\n if (lsLocale && Object.values(Locale).includes(lsLocale)) {\r\n this._locale = lsLocale;\r\n } else {\r\n const navigatorLocale = navigator.language || Locale.EN;\r\n const navigatorLanguage = navigatorLocale.split('-', 1)[0].toLowerCase();\r\n this._locale = getNavigatorLanguageFormatted(navigatorLanguage);\r\n }\r\n\r\n /* Opzione prefisso */\r\n if (options?.prefix) {\r\n this._prefix = options.prefix;\r\n }\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: set -------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Imposta l'elenco dei codici lingua supportati dall'applicazione */\r\n public static setLocalesSupported(locales: string[] | undefined): void {\r\n const list = locales ?? [];\r\n\r\n // Controllo: presenza di stringhe che non appartenenti all'enum Locale\r\n const validLocales = Object.values(Locale) as string[];\r\n const invalidLocale = list.find((lang) => !validLocales.includes(lang));\r\n\r\n if (invalidLocale) {\r\n throw new Error(`Locale '${invalidLocale}' is not supported`);\r\n }\r\n\r\n // Assegnazione valori\r\n this._localesSupported = list as Locale[];\r\n }\r\n\r\n /**\r\n * Aggiorna lo store locale con il dizionario delle traduzioni fornito.\r\n * Se viene passato undefined, lo store viene inizializzato come oggetto vuoto.\r\n */\r\n public static setTranslations(translations: Record<string, string> | undefined): void {\r\n this.store.next(translations ?? {});\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* ----------------------------- Metodi: traduzioni ------------------------------ */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Traduce una label in base al dizionario caricato.\r\n * Gestisce la composizione della chiave, i parametri dinamici (interpolazione) e il fallback.\r\n */\r\n public static translate(\r\n key: string,\r\n prefix = 'lbl',\r\n params?: Record<string, string | number | Date>,\r\n ): string {\r\n if (!key) return '-';\r\n\r\n // Costruzione chiave: prefissoGlobale + prefissoLocale + labelConInizialeMaiuscola\r\n const keyParts = key.trim().split(/(?=[A-Z])/);\r\n const rootKeyParts = keyParts.filter((p) => p.toLowerCase() !== prefix.toLowerCase());\r\n const cleanKey = rootKeyParts.length > 0 ? rootKeyParts.join('') : undefined;\r\n const capitalizedKey = cleanKey ? cleanKey.charAt(0).toUpperCase() + cleanKey.slice(1) : '';\r\n const finalKey = `${this._prefix ?? ''}${prefix}${capitalizedKey}`;\r\n\r\n // Cerca la chiave in minuscolo (standardizzazione)\r\n let translation = this.currentValue?.[finalKey.toLowerCase()];\r\n\r\n // Log e fallback se la traduzione manca\r\n if (!translation) {\r\n console.warn(`Translation missing for key: ${finalKey}`);\r\n return `🔑 ${finalKey}`;\r\n }\r\n\r\n // Interpolazione variabili\r\n if (params) {\r\n for (const [key, value] of Object.entries(params)) {\r\n const displayValue =\r\n value instanceof Date ? value.toLocaleDateString(this._locale) : String(value);\r\n\r\n translation = translation.replaceAll(`{{${key}}}`, () => displayValue);\r\n }\r\n }\r\n\r\n return translation;\r\n }\r\n\r\n /**\r\n * Traduce una stringa che contiene parametri separati da un carattere specifico.\r\n * Supporta ora un numero arbitrario di parametri in formato \"label/param1/param2\"\r\n * o semplicemente \"label\".\r\n */\r\n public static translateInlineParams(keyWithParams: string, splitChar: string): string {\r\n if (!keyWithParams) return '-';\r\n\r\n const [label, ...params] = keyWithParams.split(splitChar);\r\n\r\n // Se non ci sono parametri, esegui una traduzione semplice\r\n if (params.length === 0) {\r\n return this.translate(label);\r\n }\r\n\r\n // Mappa i parametri in un oggetto di interpolazione: { inlineParam0: val, inlineParam1: val, ... }\r\n const interpolationParameters: Record<string, string> = {};\r\n for (const [index, val] of params.entries()) {\r\n interpolationParameters[`param${index}`] = val;\r\n }\r\n\r\n return this.translate(label, 'lbl', interpolationParameters);\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* ------------------------------- Metodi: numeri -------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Converte un valore numerico in una stringa formattata secondo il locale impostato.\r\n * Disabilita i separatori delle migliaia e forza un numero fisso di decimali.\r\n */\r\n public static toStringNumber(value: number, decimal: number): string {\r\n return new Intl.NumberFormat(this._locale, {\r\n useGrouping: true,\r\n minimumFractionDigits: decimal,\r\n maximumFractionDigits: decimal,\r\n numberingSystem: 'latn',\r\n }).format(value);\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: date --------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Formatta una data o una stringa in base al locale corrente.\r\n * Gestisce tre modalità predefinite (date, time, full) e accetta opzioni personalizzate Intl.\r\n */\r\n public static toDate(\r\n date: Date | string | number,\r\n mode: 'date' | 'time' | 'full' = 'full',\r\n force?: { oldLang: string; newLocale: string },\r\n ): string {\r\n const dt = new Date(date);\r\n\r\n // Controllo: validità data\r\n if (Number.isNaN(dt.getTime())) {\r\n console.error(`[UniLocaleManager] Data non valida fornita a formatDateTime:`, date);\r\n return '';\r\n }\r\n\r\n // Controllo: locale da forzare\r\n const locale = force && this._locale.startsWith(force.oldLang) ? force.newLocale : this._locale;\r\n\r\n switch (mode) {\r\n case 'date': {\r\n return dt.toLocaleDateString(locale);\r\n }\r\n case 'time': {\r\n return dt.toLocaleTimeString(locale);\r\n }\r\n case 'full': {\r\n return dt.toLocaleString(locale);\r\n }\r\n }\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -19,9 +19,17 @@ class UniToastManager {
|
|
|
19
19
|
*/
|
|
20
20
|
static show(config) {
|
|
21
21
|
/* Messaggio tradotto */
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
let message = UniLocaleManager.translate(config.label.trim(), config.prefix, config.params);
|
|
23
|
+
/* Prefisso (già tradotto) */
|
|
24
|
+
if (config.message?.prefix) {
|
|
25
|
+
message = `${config.message.prefix} ${message}`;
|
|
26
|
+
}
|
|
27
|
+
/* Suffisso (già tradotto) */
|
|
28
|
+
if (config.message?.suffix) {
|
|
29
|
+
message += ` ${config.message.suffix}`;
|
|
30
|
+
}
|
|
31
|
+
/* Esecuzione del toast (dipende dalla librerai associata) */
|
|
32
|
+
this.manager[config.type ?? 'info'](message, config);
|
|
25
33
|
}
|
|
26
34
|
/**
|
|
27
35
|
* Mostra un toast di successo basato su una risposta HTTP e una label di traduzione.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uni-manager-toast.mjs","sources":["../../../projects/uni-manager/toast/manager.ts","../../../projects/uni-manager/toast/uni-manager-toast.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { UniLocaleManager } from 'uni-manager/locale';\r\nimport type { IToastManager, ToastConfig, ToastHttpConfig } from 'uni-model-type/type';\r\n\r\nexport class UniToastManager {\r\n /* ------------------------------------------------------------------------------- */\r\n /* ----------------------------------- Config ------------------------------------ */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Riferimento interno all'istanza */\r\n private static manager: IToastManager;\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: setup -------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Inizializza il manager con una serie di operazioni\r\n */\r\n public static setup(operations: IToastManager): void {\r\n this.manager = operations;\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: show --------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Mostra un toast di successo basato su una risposta HTTP e una label di traduzione.\r\n */\r\n public static show(
|
|
1
|
+
{"version":3,"file":"uni-manager-toast.mjs","sources":["../../../projects/uni-manager/toast/manager.ts","../../../projects/uni-manager/toast/uni-manager-toast.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { UniLocaleManager } from 'uni-manager/locale';\r\nimport type { IToastManager, ToastConfig, ToastHttpConfig } from 'uni-model-type/type';\r\n\r\nexport class UniToastManager {\r\n /* ------------------------------------------------------------------------------- */\r\n /* ----------------------------------- Config ------------------------------------ */\r\n /* ------------------------------------------------------------------------------- */\r\n /** Riferimento interno all'istanza */\r\n private static manager: IToastManager;\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: setup -------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Inizializza il manager con una serie di operazioni\r\n */\r\n public static setup(operations: IToastManager): void {\r\n this.manager = operations;\r\n }\r\n\r\n /* ------------------------------------------------------------------------------- */\r\n /* -------------------------------- Metodi: show --------------------------------- */\r\n /* ------------------------------------------------------------------------------- */\r\n /**\r\n * Mostra un toast di successo basato su una risposta HTTP e una label di traduzione.\r\n */\r\n public static show(config: ToastConfig): void {\r\n /* Messaggio tradotto */\r\n let message = UniLocaleManager.translate(config.label.trim(), config.prefix, config.params);\r\n\r\n /* Prefisso (già tradotto) */\r\n if (config.message?.prefix) {\r\n message = `${config.message.prefix} ${message}`;\r\n }\r\n\r\n /* Suffisso (già tradotto) */\r\n if (config.message?.suffix) {\r\n message += ` ${config.message.suffix}`;\r\n }\r\n\r\n /* Esecuzione del toast (dipende dalla librerai associata) */\r\n this.manager[config.type ?? 'info'](message, config);\r\n }\r\n\r\n /**\r\n * Mostra un toast di successo basato su una risposta HTTP e una label di traduzione.\r\n */\r\n public static showHttp<T>(config: ToastConfig & ToastHttpConfig<T>, res: T | undefined): void {\r\n const { params, resParams, formatters } = config;\r\n\r\n /* Parametri statici di base */\r\n const allParams: Record<string, any> = { ...params };\r\n\r\n if (res !== undefined && res !== null) {\r\n /* Se è un array aggiunge il parametro 'count' con la lunghezza dell'array */\r\n if (Array.isArray(res)) {\r\n allParams['count'] = res.length;\r\n } else if (typeof res === 'object' && resParams?.length) {\r\n const params = resParams ?? [];\r\n // Se la proprietà NON esiste nella risposta, allora salta\r\n for (const param of params) {\r\n if (!Object.hasOwn(res, param)) continue;\r\n\r\n // Se esiste un formatter per questa chiave lo si usa, altrimenti valore grezzo\r\n const rawValue = res[param];\r\n const formatter = formatters?.[param];\r\n allParams[param] = formatter ? formatter(rawValue) : rawValue;\r\n }\r\n }\r\n }\r\n\r\n /* Messaggio tradotto */\r\n this.show({ ...config, params: allParams });\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;AAAA;MAIa,eAAe,CAAA;;;;AAU1B;;AAEG;IACI,OAAO,KAAK,CAAC,UAAyB,EAAA;AAC3C,QAAA,IAAI,CAAC,OAAO,GAAG,UAAU;IAC3B;;;;AAKA;;AAEG;IACI,OAAO,IAAI,CAAC,MAAmB,EAAA;;QAEpC,IAAI,OAAO,GAAG,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;;AAG3F,QAAA,IAAI,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE;YAC1B,OAAO,GAAG,CAAA,EAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAA,CAAA,EAAI,OAAO,CAAA,CAAE;QACjD;;AAGA,QAAA,IAAI,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE;YAC1B,OAAO,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE;QACxC;;AAGA,QAAA,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC;IACtD;AAEA;;AAEG;AACI,IAAA,OAAO,QAAQ,CAAI,MAAwC,EAAE,GAAkB,EAAA;QACpF,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,MAAM;;AAGhD,QAAA,MAAM,SAAS,GAAwB,EAAE,GAAG,MAAM,EAAE;QAEpD,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI,EAAE;;AAErC,YAAA,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;AACtB,gBAAA,SAAS,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM;YACjC;iBAAO,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,SAAS,EAAE,MAAM,EAAE;AACvD,gBAAA,MAAM,MAAM,GAAG,SAAS,IAAI,EAAE;;AAE9B,gBAAA,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;oBAC1B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC;wBAAE;;AAGhC,oBAAA,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC;AAC3B,oBAAA,MAAM,SAAS,GAAG,UAAU,GAAG,KAAK,CAAC;AACrC,oBAAA,SAAS,CAAC,KAAK,CAAC,GAAG,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,GAAG,QAAQ;gBAC/D;YACF;QACF;;AAGA,QAAA,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAC7C;AACD;;AC3ED;;AAEG;;;;"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uni-manager",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.49",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"rxjs": ">=7.8.2",
|
|
6
6
|
"lodash-es": ">=4.18.1",
|
|
7
|
-
"uni-model-type": ">=0.1.
|
|
8
|
-
"uni-error": ">=0.1.
|
|
7
|
+
"uni-model-type": ">=0.1.22",
|
|
8
|
+
"uni-error": ">=0.1.23"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"tslib": "^2.3.0"
|
|
@@ -2,18 +2,20 @@ import { Observable } from 'rxjs';
|
|
|
2
2
|
import { ErrorStore, IUniHttpError, IUniFeError } from 'uni-model-type/type';
|
|
3
3
|
|
|
4
4
|
declare class UniErrorManager {
|
|
5
|
-
/** Restituisce la lista degli errori visibili */
|
|
6
|
-
static get errorStoreItems$(): Observable<({
|
|
7
|
-
id: string;
|
|
8
|
-
} & ErrorStore)[]>;
|
|
9
|
-
/** Restituisce se lo store ha errori visibili o meno */
|
|
10
|
-
static get hasErrors$(): Observable<boolean>;
|
|
11
5
|
/** Store privato (Subject) */
|
|
12
6
|
private static store;
|
|
13
7
|
/** Store pubblico (Observable) */
|
|
14
8
|
static store$: Observable<Map<string, ErrorStore>>;
|
|
15
9
|
/** Ottiene lo stato attuale della Map senza dover sottoscrivere l'observable */
|
|
16
10
|
static get currentValue(): Map<string, ErrorStore>;
|
|
11
|
+
/** Restituisce la lista degli errori visibili */
|
|
12
|
+
static get errors$(): Observable<({
|
|
13
|
+
id: string;
|
|
14
|
+
} & ErrorStore)[]>;
|
|
15
|
+
/** Restituisce se lo store ha errori visibili o meno */
|
|
16
|
+
static get hasErrors$(): Observable<boolean>;
|
|
17
|
+
/** Restituisce se lo store ha errori visibili */
|
|
18
|
+
static get hasVisibleErrors$(): Observable<boolean>;
|
|
17
19
|
/**
|
|
18
20
|
* Aggiunge o aggiorna un errore nello store (lo rende automaticamente visibile).
|
|
19
21
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BehaviorSubject, Observable } from 'rxjs';
|
|
2
2
|
import { HttpRef, HttpConfig, HttpBodyPrimitive, HttpBody, FileDatasource, HttpConfigPolling } from 'uni-model-type/type';
|
|
3
3
|
|
|
4
4
|
declare class UniHttpManager {
|
|
@@ -6,19 +6,40 @@ declare class UniHttpManager {
|
|
|
6
6
|
private static hostname;
|
|
7
7
|
/** Porta del server su cui effettuare le chiamate (es. 80, 443 o 3000) */
|
|
8
8
|
private static port;
|
|
9
|
-
/** Restituisce se lo store ha chiamate in attesa di risposta o meno */
|
|
10
|
-
static get hasWaitingRequests$(): Observable<boolean>;
|
|
11
9
|
/** Store privato (Subject) */
|
|
12
10
|
static store: BehaviorSubject<Map<string, HttpRef>>;
|
|
13
11
|
/** Store pubblico (Observable) */
|
|
14
12
|
static store$: Observable<Map<string, HttpRef>>;
|
|
15
13
|
/** Ottiene lo stato attuale della Map senza dover sottoscrivere l'observable */
|
|
16
14
|
static get currentValue(): Map<string, HttpRef>;
|
|
15
|
+
/** Restituisce se lo store ha chiamate in attesa di risposta o meno */
|
|
16
|
+
static get hasWaitingRequests$(): Observable<boolean>;
|
|
17
17
|
/**
|
|
18
18
|
* Inizializza la configurazione di rete del manager.
|
|
19
19
|
* Deve essere chiamato prima di effettuare qualsiasi richiesta HTTP.
|
|
20
20
|
*/
|
|
21
21
|
static setup(hostname: string, port: number): void;
|
|
22
|
+
/**
|
|
23
|
+
* Aggiunge una nuova ref nello store solo se non è già presente.
|
|
24
|
+
* Se l'ID esiste già, l'operazione viene interrotta per preservare il dato originale.
|
|
25
|
+
*/
|
|
26
|
+
static add(id: string, url: URL, type: HttpRef['type']): void;
|
|
27
|
+
/**
|
|
28
|
+
* Rimuove un http ref tramite ID
|
|
29
|
+
*/
|
|
30
|
+
static remove(id: string): void;
|
|
31
|
+
/**
|
|
32
|
+
* Aggiorna il contatore delle chiamate pendenti per una specifica ref.
|
|
33
|
+
* Incrementa o decrementa 'pendingCount' garantendo che non scenda mai sotto lo zero.
|
|
34
|
+
* Se la ref non esiste, l'operazione viene ignorata.
|
|
35
|
+
*/
|
|
36
|
+
static updateIsLoading(id: string, delta: -1 | 1): void;
|
|
37
|
+
/**
|
|
38
|
+
* Aggiorna lo stato di errore per una specifica ref.
|
|
39
|
+
* Se il valore di 'hasError' è identico a quello attuale o se la ref non esiste,
|
|
40
|
+
* l'operazione viene interrotta per evitare aggiornamenti inutili.
|
|
41
|
+
*/
|
|
42
|
+
static updateHasError(id: string, hasError: boolean): void;
|
|
22
43
|
static read$(config: HttpConfig<void>): Observable<void>;
|
|
23
44
|
static read$<T>(config: HttpConfig<T>): Observable<T>;
|
|
24
45
|
/**
|
|
@@ -10,10 +10,7 @@ declare class UniToastManager {
|
|
|
10
10
|
/**
|
|
11
11
|
* Mostra un toast di successo basato su una risposta HTTP e una label di traduzione.
|
|
12
12
|
*/
|
|
13
|
-
static show(config: ToastConfig
|
|
14
|
-
prefix?: string;
|
|
15
|
-
suffix?: string;
|
|
16
|
-
}): void;
|
|
13
|
+
static show(config: ToastConfig): void;
|
|
17
14
|
/**
|
|
18
15
|
* Mostra un toast di successo basato su una risposta HTTP e una label di traduzione.
|
|
19
16
|
*/
|