uni-manager 0.1.0 → 0.1.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"uni-manager-locale.mjs","sources":["../../../projects/uni-manager/locale/manager.ts","../../../projects/uni-manager/locale/uni-manager-locale.ts"],"sourcesContent":["import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';\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 = navigator.language ?? 'en-US';\r\n\r\n /** Elenco dei codici lingua supportati dall'applicazione (es. ['it-IT', 'en-US']) */\r\n private static _localesSupported: string[] = [];\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(): string {\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(): string[] {\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('-')[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(locale: string | null | undefined, prefix?: string): void {\r\n this._locale = locale ?? 'en-US';\r\n this._prefix = prefix;\r\n }\r\n\r\n /** Imposta l'elenco dei codici lingua supportati dall'applicazione */\r\n public static setLocalesSupported(locales: string[] | undefined): void {\r\n this._localesSupported = locales ?? [];\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 interpolationParams?: 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 (interpolationParams) {\r\n for (const [key, value] of Object.entries(interpolationParams)) {\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: string | Date,\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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"}
1
+ {"version":3,"file":"uni-manager-locale.mjs","sources":["../../../projects/uni-manager/locale/manager.ts","../../../projects/uni-manager/locale/uni-manager-locale.ts"],"sourcesContent":["import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';\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 = navigator.language ?? 'en-US';\r\n\r\n /** Elenco dei codici lingua supportati dall'applicazione (es. ['it-IT', 'en-US']) */\r\n private static _localesSupported: string[] = [];\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(): string {\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(): string[] {\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('-')[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(locale: string | null | undefined, prefix?: string): void {\r\n this._locale = locale ?? 'en-US';\r\n this._prefix = prefix;\r\n }\r\n\r\n /** Imposta l'elenco dei codici lingua supportati dall'applicazione */\r\n public static setLocalesSupported(locales: string[] | undefined): void {\r\n this._localesSupported = locales ?? [];\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: string | Date,\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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"}
@@ -27,22 +27,24 @@ class UniToastManager {
27
27
  * Mostra un toast di successo basato su una risposta HTTP e una label di traduzione.
28
28
  */
29
29
  static showHttp(config, res) {
30
- const { interpolationParams, resParams, resLengthParam, formatters } = config;
30
+ const { params, resParams, formatters } = config;
31
31
  /* Parametri statici di base */
32
- const allParams = { ...interpolationParams };
33
- /* Config parametri risposta: estrazione parametri dalla risposta (se esiste ed è un oggetto) */
34
- if (resParams?.length && res && typeof res === 'object') {
35
- for (const param of resParams ?? []) {
36
- if (param in res)
37
- continue;
38
- // Se esiste un formatter per questa chiave lo si usa, altrimenti valore grezzo
39
- const rawValue = res[param];
40
- allParams[param] = formatters?.[param] ? formatters[param](rawValue) : rawValue;
32
+ const allParams = { ...params };
33
+ if (res !== undefined && res !== null) {
34
+ /* Se è un array aggiunge il parametro 'count' con la lunghezza dell'array */
35
+ if (Array.isArray(res)) {
36
+ allParams['count'] = res.length;
37
+ }
38
+ else if (typeof res === 'object' && resParams?.length) {
39
+ // Se la proprietà NON esiste nella risposta, allora salta
40
+ for (const resParam of resParams ?? []) {
41
+ if (!(resParam in res))
42
+ continue;
43
+ // Se esiste un formatter per questa chiave lo si usa, altrimenti valore grezzo
44
+ const rawValue = res[resParam];
45
+ allParams[resParam] = formatters?.[resParam] ? formatters[resParam](rawValue) : rawValue;
46
+ }
41
47
  }
42
- }
43
- /* Config parametro lunghezza risposta: conteggio array */
44
- if (resLengthParam && Array.isArray(res)) {
45
- allParams[resLengthParam] = res.length;
46
48
  }
47
49
  /* Messaggio tradotto */
48
50
  this.show({ ...config, params: allParams });
@@ -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 './model';\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(\r\n config: Omit<ToastConfig, 'interpolationParams'> & {\r\n params?: Record<string, any>;\r\n prefix?: string;\r\n suffix?: string;\r\n },\r\n ): void {\r\n /* Messaggio tradotto */\r\n const msg = UniLocaleManager.translate(config.label, 'toast', config.params);\r\n const msgFixed = `${config.prefix ?? ''}${msg}${config.suffix ?? ''}`;\r\n this.manager[config.type ?? 'info'](msgFixed, 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 { interpolationParams, resParams, resLengthParam, formatters } = config;\r\n\r\n /* Parametri statici di base */\r\n const allParams: Record<string, any> = { ...interpolationParams };\r\n\r\n /* Config parametri risposta: estrazione parametri dalla risposta (se esiste ed è un oggetto) */\r\n if (resParams?.length && res && typeof res === 'object') {\r\n for (const param of resParams ?? []) {\r\n if (param in res) 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 allParams[param] = formatters?.[param] ? formatters[param](rawValue) : rawValue;\r\n }\r\n }\r\n\r\n /* Config parametro lunghezza risposta: conteggio array */\r\n if (resLengthParam && Array.isArray(res)) {\r\n allParams[resLengthParam] = res.length;\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,CAChB,MAIC,EAAA;;AAGD,QAAA,MAAM,GAAG,GAAG,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC;AAC5E,QAAA,MAAM,QAAQ,GAAG,CAAA,EAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAA,EAAG,GAAG,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE;AACrE,QAAA,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC;IACvD;AAEA;;AAEG;AACI,IAAA,OAAO,QAAQ,CAAI,MAAwC,EAAE,GAAkB,EAAA;QACpF,MAAM,EAAE,mBAAmB,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,GAAG,MAAM;;AAG7E,QAAA,MAAM,SAAS,GAAwB,EAAE,GAAG,mBAAmB,EAAE;;QAGjE,IAAI,SAAS,EAAE,MAAM,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;AACvD,YAAA,KAAK,MAAM,KAAK,IAAI,SAAS,IAAI,EAAE,EAAE;gBACnC,IAAI,KAAK,IAAI,GAAG;oBAAE;;AAGlB,gBAAA,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC;gBAC3B,SAAS,CAAC,KAAK,CAAC,GAAG,UAAU,GAAG,KAAK,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,GAAG,QAAQ;YACjF;QACF;;QAGA,IAAI,cAAc,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;AACxC,YAAA,SAAS,CAAC,cAAc,CAAC,GAAG,GAAG,CAAC,MAAM;QACxC;;AAGA,QAAA,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAC7C;AACD;;ACpED;;AAEG;;;;"}
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 './model';\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(\r\n config: ToastConfig & {\r\n prefix?: string;\r\n suffix?: string;\r\n },\r\n ): void {\r\n /* Messaggio tradotto */\r\n const msg = UniLocaleManager.translate(config.label, 'toast', config.params);\r\n const msgFixed = `${config.prefix ?? ''}${msg}${config.suffix ?? ''}`;\r\n this.manager[config.type ?? 'info'](msgFixed, 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 // Se la proprietà NON esiste nella risposta, allora salta\r\n for (const resParam of resParams ?? []) {\r\n if (!(resParam in res)) continue;\r\n\r\n // Se esiste un formatter per questa chiave lo si usa, altrimenti valore grezzo\r\n const rawValue = res[resParam];\r\n allParams[resParam] = formatters?.[resParam] ? formatters[resParam](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,CAChB,MAGC,EAAA;;AAGD,QAAA,MAAM,GAAG,GAAG,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC;AAC5E,QAAA,MAAM,QAAQ,GAAG,CAAA,EAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAA,EAAG,GAAG,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE;AACrE,QAAA,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC;IACvD;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;;AAEvD,gBAAA,KAAK,MAAM,QAAQ,IAAI,SAAS,IAAI,EAAE,EAAE;AACtC,oBAAA,IAAI,EAAE,QAAQ,IAAI,GAAG,CAAC;wBAAE;;AAGxB,oBAAA,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;oBAC9B,SAAS,CAAC,QAAQ,CAAC,GAAG,UAAU,GAAG,QAAQ,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,QAAQ;gBAC1F;YACF;QACF;;AAGA,QAAA,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAC7C;AACD;;ACnED;;AAEG;;;;"}
@@ -17,7 +17,7 @@ import { concatMap } from 'rxjs/internal/operators/concatMap';
17
17
  import { exhaustMap } from 'rxjs/internal/operators/exhaustMap';
18
18
  import { mergeMap } from 'rxjs/internal/operators/mergeMap';
19
19
  import { switchMap } from 'rxjs/internal/operators/switchMap';
20
- import { UniHttpError, isHttpErrorBody } from 'uni-error/http';
20
+ import { UniHttpError, isHttpException } from 'uni-error/http';
21
21
  import { UniTypeDateManager as UniTypeDateManager$1 } from 'uni-manager/type';
22
22
  import { UniLocaleManager as UniLocaleManager$1 } from 'uni-manager/locale';
23
23
 
@@ -207,28 +207,27 @@ function operatorHandler(operator) {
207
207
  }
208
208
  function errorHandler(err, errorMode, ref) {
209
209
  // Controllo: sia effettivamente un errore di tipo 'UniHttpError'
210
- if (!(err instanceof UniHttpError)) {
211
- return throwError(() => err);
212
- }
213
- // Aggiorna la ref nella map
214
- updateHasError(ref, true);
215
- // Gestione dell'errore in base al parametro
216
- switch (errorMode) {
217
- case PollingErrorMode.IGNORE: {
218
- return of();
219
- }
220
- case PollingErrorMode.SKIP: {
221
- return EMPTY;
222
- }
223
- case PollingErrorMode.IGNORE_WITH_ERROR: {
224
- UniErrorManager$1.add(ref, err);
225
- return of();
226
- }
227
- case PollingErrorMode.STOP: {
228
- UniErrorManager$1.add(ref, err);
229
- return throwError(() => err);
210
+ if (err instanceof UniHttpError) {
211
+ switch (errorMode) {
212
+ case PollingErrorMode.IGNORE: {
213
+ return of();
214
+ }
215
+ case PollingErrorMode.SKIP: {
216
+ return EMPTY;
217
+ }
218
+ case PollingErrorMode.IGNORE_WITH_ERROR: {
219
+ UniErrorManager$1.add(ref, err);
220
+ return of();
221
+ }
222
+ case PollingErrorMode.STOP: {
223
+ UniErrorManager$1.add(ref, err);
224
+ return throwError(() => err);
225
+ }
230
226
  }
231
227
  }
228
+ else {
229
+ return throwError(() => err);
230
+ }
232
231
  }
233
232
 
234
233
  /* ------------------------------------------------------------------------------- */
@@ -263,6 +262,8 @@ function http$(url, refType, config, promiseFactory) {
263
262
  }
264
263
  },
265
264
  }), catchError((err) => {
265
+ // Aggiorna la ref nella map
266
+ updateHasError(ref, true);
266
267
  /* Gestione errore */
267
268
  return errorHandler(err, PollingErrorMode.STOP, ref);
268
269
  }), finalize(() => {
@@ -308,6 +309,8 @@ function httpPolling$(url, config, promiseFactory) {
308
309
  UniToastManager$1.showHttp(firstIteration.toast, res);
309
310
  }
310
311
  }), catchError((err) => {
312
+ // Aggiorna la ref nella map
313
+ updateHasError(ref, true);
311
314
  /* Gestione errore */
312
315
  return errorHandler(err, errorMode, ref);
313
316
  }), finalize(() => {
@@ -409,66 +412,65 @@ function updateHasError(id, hasError) {
409
412
  // Aggiorna il nuovo stato notificando l'observer
410
413
  UniHttpManager.store.next(newMap);
411
414
  }
412
- /**
413
- * Svuota completamente la lista delle refs
414
- */
415
- function removeAll() {
416
- // Crea una nuova istanza della Map
417
- const newMap = new Map();
418
- // Aggiorna il nuovo stato notificando l'observer
419
- UniHttpManager.store.next(newMap);
420
- }
421
415
 
422
416
  async function execute(url, init) {
423
417
  try {
424
- /* Esegue chiamata http */
418
+ /* Esecuzione della richiesta HTTP nativa */
425
419
  const res = await fetch(url, init);
426
- /* Nessun contenuto cons status 204 */
420
+ /* Gestione dello stato 204: assenza di contenuto legittima */
427
421
  if (res.status === 204) {
428
422
  return undefined;
429
423
  }
430
- /* Recupero se è un json */
431
- const contentType = res.headers.get('content-type') ?? '';
432
- const isJson = contentType.startsWith('application/json');
433
- /* Errore HTTP (quindi risposta ricevuta ma non ok) */
434
- if (!res.ok) {
435
- let errorBody;
436
- try {
437
- /* Clona risposta solo se c'è errore, per leggerla senza consumare la originale */
438
- const resClone = res.clone();
439
- /* Aggiorna body con struttura errore */
440
- errorBody = isJson ? await resClone.json() : await resClone.text();
441
- }
442
- catch {
443
- errorBody = await res.text();
444
- }
445
- if (isHttpErrorBody(errorBody)) {
446
- const type = errorBody.exceptionType.includes('HttpRequestException') ? 'be' : 'ice';
447
- throw new UniHttpError(type, res.status, url, errorBody);
448
- }
449
- else {
450
- const error = new Error(`HTTP ${res.statusText}`);
451
- throw new UniHttpError('base', res.status, url, {
452
- exceptionMessage: error.message,
453
- exceptionType: 'ErrorBase',
454
- message: error.message,
455
- stackTrace: error.stack ?? '',
456
- });
457
- }
424
+ /*Gestione ok HTTP: risposta ricevuta dal server con stato valido */
425
+ if (res.ok) {
426
+ return res;
427
+ }
428
+ /* Gestione Errore HTTP: risposta ricevuta dal server ma con stato non valido */
429
+ let httpErrorPayload;
430
+ try {
431
+ /* Clonazione della risposta per l'ispezione del payload senza consumare lo stream originale */
432
+ const resClone = res.clone();
433
+ /* Recupero se è un json */
434
+ const contentType = res.headers.get('content-type') ?? '';
435
+ const isJson = contentType.startsWith('application/json');
436
+ /* Estrazione del corpo dell'errore in base al formato rilevato */
437
+ httpErrorPayload = isJson ? await resClone.json() : await resClone.text();
438
+ }
439
+ catch {
440
+ /* Fallback in caso di fallimento della clonazione o del parsing del testo */
441
+ httpErrorPayload = `Failed to parse error response body (Status: ${res.status})`;
442
+ }
443
+ // Controllo: se il payload estratto rispetta è di tipo HttpException
444
+ if (isHttpException(httpErrorPayload)) {
445
+ // const type = httpErrorPayload.isBe ? 'be' : 'ice';
446
+ throw new UniHttpError('be', res.status, url, httpErrorPayload);
447
+ }
448
+ else {
449
+ // Fallback per errori non di tipo HttpException (es. pagine HTML di errore di IIS/Nginx o stringhe piane)
450
+ const error = new Error(res.statusText || `HTTP Error ${res.status}`);
451
+ const fallbackException = {
452
+ message: typeof httpErrorPayload === 'string' && httpErrorPayload
453
+ ? httpErrorPayload
454
+ : error.message,
455
+ type: 'ErrorBase',
456
+ stackTrace: error.stack ?? '',
457
+ isBe: true,
458
+ };
459
+ throw new UniHttpError('base', res.status, url, fallbackException);
458
460
  }
459
- /* Risposta ok */
460
- return res;
461
461
  }
462
462
  catch (error) {
463
+ // Fallback per errori di rete locale (es. assenza di linea, DNS fallito, timeout di fetch)
463
464
  if (error instanceof TypeError) {
464
- throw new UniHttpError('network', -1, url, {
465
- exceptionMessage: `${error.name}: ${error.message}\n${error.stack}`,
466
- exceptionType: error.name,
465
+ const fallbackNetworkException = {
467
466
  message: error.message,
467
+ type: error.name || 'TypeError',
468
468
  stackTrace: error.stack ?? '',
469
- });
469
+ isBe: true,
470
+ };
471
+ throw new UniHttpError('network', -1, url, fallbackNetworkException);
470
472
  }
471
- // Fallback
473
+ // Rilancio diretto senza alterazioni per istanze di UniHttpError o eccezioni non identificate
472
474
  throw error;
473
475
  }
474
476
  }
@@ -515,16 +517,16 @@ async function executeBlob(url, init) {
515
517
  * Costruisce un URL completo per l'API partendo dai parametri di configurazione.
516
518
  */
517
519
  function getUrl(hostname, port, config) {
518
- const { params, path, hasApiPrefix = true } = config;
520
+ const { pathParams, path, hasApiPrefix } = config;
519
521
  // Costruzione url
520
- const prefix = hasApiPrefix ? 'api' : '';
522
+ const prefix = hasApiPrefix === false ? '' : 'api';
521
523
  const cleanPath = path.startsWith('/') ? path.slice(1) : path;
522
524
  const pathFixed = prefix ? `${prefix}/${cleanPath}` : cleanPath;
523
525
  const url = new URL(pathFixed, `http://${hostname}:${port}`);
524
- if (params) {
526
+ if (pathParams) {
525
527
  // Regex per intercettare stringhe in formato ISO string
526
528
  const isoDateRegex = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?)?$/;
527
- for (const [key, rawValue] of Object.entries(params)) {
529
+ for (const [key, rawValue] of Object.entries(pathParams)) {
528
530
  if (rawValue === undefined || rawValue === null) {
529
531
  continue;
530
532
  }
@@ -641,7 +643,7 @@ class UniHttpManager {
641
643
  ...config.init,
642
644
  method: 'GET',
643
645
  };
644
- /* Chiama API */
646
+ /* API */
645
647
  const url = getUrl(this.hostname, this.port, config);
646
648
  return http$(url, 'one', config, () => executeHttp(url, initCustom)).pipe(tap((res) => {
647
649
  if (Array.isArray(res) && config.toast === undefined) {
@@ -667,12 +669,12 @@ class UniHttpManager {
667
669
  },
668
670
  body: JSON.stringify(normalizeHttpBody(body)),
669
671
  };
670
- /* Toast di default */
672
+ /* Config custom (toast di default) */
671
673
  const configCustom = {
672
674
  ...config,
673
- toast: config.toast === null ? undefined : (config.toast ?? CONFIG_TOAST_DEFAULT),
675
+ toast: config.hasToast === false ? undefined : (config.toast ?? CONFIG_TOAST_DEFAULT),
674
676
  };
675
- /* Chiama API */
677
+ /* API */
676
678
  const url = getUrl(this.hostname, this.port, config);
677
679
  return http$(url, 'one', configCustom, () => executeHttp(url, initCustom));
678
680
  }
@@ -689,12 +691,12 @@ class UniHttpManager {
689
691
  };
690
692
  initCustom.body = JSON.stringify(normalizeHttpBody(body));
691
693
  }
692
- /* Toast di default */
694
+ /* Config custom (toast di default) */
693
695
  const configCustom = {
694
696
  ...config,
695
- toast: config.toast === null ? undefined : (config.toast ?? CONFIG_TOAST_DEFAULT),
697
+ toast: config.hasToast === false ? undefined : (config.toast ?? CONFIG_TOAST_DEFAULT),
696
698
  };
697
- /* Chiama API */
699
+ /* API */
698
700
  const url = getUrl(this.hostname, this.port, config);
699
701
  return http$(url, 'one', configCustom, () => executeHttp(url, initCustom));
700
702
  }
@@ -708,12 +710,12 @@ class UniHttpManager {
708
710
  ...config.init,
709
711
  method: 'DELETE',
710
712
  };
711
- /* Toast di default */
713
+ /* Config custom (toast di default) */
712
714
  const configCustom = {
713
715
  ...config,
714
- toast: config.toast === null ? undefined : (config.toast ?? CONFIG_TOAST_DEFAULT),
716
+ toast: config.hasToast === false ? undefined : (config.toast ?? CONFIG_TOAST_DEFAULT),
715
717
  };
716
- /* Chiama API */
718
+ /* API */
717
719
  const url = getUrl(this.hostname, this.port, config);
718
720
  return http$(url, 'one', configCustom, () => executeHttp(url, initCustom));
719
721
  }
@@ -730,9 +732,9 @@ class UniHttpManager {
730
732
  ...config.init,
731
733
  method: 'GET',
732
734
  };
733
- /* Chiama API */
735
+ /* API */
734
736
  const url = getUrl(this.hostname, this.port, config);
735
- return http$(url, 'one', config, () => executeBlob(url, initCustom));
737
+ return http$(url, 'image', config, () => executeBlob(url, initCustom));
736
738
  }
737
739
  /**
738
740
  * Recupera un file (es. PDF) tramite una richiesta GET e restituisce un Object URL temporaneo.
@@ -744,12 +746,12 @@ class UniHttpManager {
744
746
  ...config.init,
745
747
  method: 'GET',
746
748
  };
747
- /* Toast di default */
749
+ /* Config custom (toast di default) */
748
750
  const configCustom = {
749
751
  ...config,
750
- toast: config.toast === null ? undefined : (config.toast ?? CONFIG_TOAST_DEFAULT),
752
+ toast: config.hasToast === false ? undefined : (config.toast ?? CONFIG_TOAST_DEFAULT),
751
753
  };
752
- /* Chiama API */
754
+ /* API */
753
755
  const url = getUrl(this.hostname, this.port, config);
754
756
  return http$(url, 'file', configCustom, () => executeBlob(url, initCustom));
755
757
  }
@@ -766,7 +768,7 @@ class UniHttpManager {
766
768
  ...config.init,
767
769
  method: 'GET',
768
770
  };
769
- /* Chiama API */
771
+ /* API */
770
772
  const url = getUrl(this.hostname, this.port, config);
771
773
  return httpPolling$(url, config, () => executeHttp(url, initCustom));
772
774
  }
@@ -782,7 +784,7 @@ class UniHttpManager {
782
784
  headers: { 'Content-Type': 'application/json' },
783
785
  body: JSON.stringify(body),
784
786
  };
785
- /* Chiama API */
787
+ /* API */
786
788
  const url = getUrl(this.hostname, this.port, config);
787
789
  return httpPolling$(url, config, () => executeHttp(url, initCustom));
788
790
  }
@@ -802,7 +804,7 @@ class UniHttpManager {
802
804
  };
803
805
  initCustom.body = JSON.stringify(body);
804
806
  }
805
- /* Chiama API */
807
+ /* API */
806
808
  const url = getUrl(this.hostname, this.port, config);
807
809
  return httpPolling$(url, config, () => executeHttp(url, initCustom));
808
810
  }
@@ -878,7 +880,7 @@ class UniLocaleManager {
878
880
  * Traduce una label in base al dizionario caricato.
879
881
  * Gestisce la composizione della chiave, i parametri dinamici (interpolazione) e il fallback.
880
882
  */
881
- static translate(key, prefix = 'lbl', interpolationParams) {
883
+ static translate(key, prefix = 'lbl', params) {
882
884
  if (!key)
883
885
  return '-';
884
886
  // Costruzione chiave: prefissoGlobale + prefissoLocale + LabelConInizialeMaiuscola
@@ -895,8 +897,8 @@ class UniLocaleManager {
895
897
  return `🔑 ${finalKey}`;
896
898
  }
897
899
  // Interpolazione variabili
898
- if (interpolationParams) {
899
- for (const [key, value] of Object.entries(interpolationParams)) {
900
+ if (params) {
901
+ for (const [key, value] of Object.entries(params)) {
900
902
  const displayValue = value instanceof Date ? value.toLocaleDateString(this._locale) : String(value);
901
903
  translation = translation.replaceAll(`{{${key}}}`, displayValue);
902
904
  }
@@ -995,22 +997,24 @@ class UniToastManager {
995
997
  * Mostra un toast di successo basato su una risposta HTTP e una label di traduzione.
996
998
  */
997
999
  static showHttp(config, res) {
998
- const { interpolationParams, resParams, resLengthParam, formatters } = config;
1000
+ const { params, resParams, formatters } = config;
999
1001
  /* Parametri statici di base */
1000
- const allParams = { ...interpolationParams };
1001
- /* Config parametri risposta: estrazione parametri dalla risposta (se esiste ed è un oggetto) */
1002
- if (resParams?.length && res && typeof res === 'object') {
1003
- for (const param of resParams ?? []) {
1004
- if (param in res)
1005
- continue;
1006
- // Se esiste un formatter per questa chiave lo si usa, altrimenti valore grezzo
1007
- const rawValue = res[param];
1008
- allParams[param] = formatters?.[param] ? formatters[param](rawValue) : rawValue;
1002
+ const allParams = { ...params };
1003
+ if (res !== undefined && res !== null) {
1004
+ /* Se è un array aggiunge il parametro 'count' con la lunghezza dell'array */
1005
+ if (Array.isArray(res)) {
1006
+ allParams['count'] = res.length;
1007
+ }
1008
+ else if (typeof res === 'object' && resParams?.length) {
1009
+ // Se la proprietà NON esiste nella risposta, allora salta
1010
+ for (const resParam of resParams ?? []) {
1011
+ if (!(resParam in res))
1012
+ continue;
1013
+ // Se esiste un formatter per questa chiave lo si usa, altrimenti valore grezzo
1014
+ const rawValue = res[resParam];
1015
+ allParams[resParam] = formatters?.[resParam] ? formatters[resParam](rawValue) : rawValue;
1016
+ }
1009
1017
  }
1010
- }
1011
- /* Config parametro lunghezza risposta: conteggio array */
1012
- if (resLengthParam && Array.isArray(res)) {
1013
- allParams[resLengthParam] = res.length;
1014
1018
  }
1015
1019
  /* Messaggio tradotto */
1016
1020
  this.show({ ...config, params: allParams });