@geosdi/ngx-geocoding 1.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"geosdi-ngx-geocoding.mjs","sources":["../../../../projects/geosdi/support/ngx-geocoding/src/lib/ngx-geocoding.module.ts","../../../../projects/geosdi/support/ngx-geocoding/src/lib/ngx-geocoding.config.ts","../../../../projects/geosdi/support/ngx-geocoding/src/lib/google-maps-sdk.ts","../../../../projects/geosdi/support/ngx-geocoding/src/lib/ngx-geocoding.service.ts","../../../../projects/geosdi/support/ngx-geocoding/src/lib/model/ngx-geocoding-config.model.ts","../../../../projects/geosdi/support/ngx-geocoding/src/index.ts","../../../../projects/geosdi/support/ngx-geocoding/src/geosdi-ngx-geocoding.ts"],"sourcesContent":["import { NgModule } from \"@angular/core\";\n\n/**\n * @author Vito Salvia - CNR IMAA geoSDI Group\n * @email vito.salvia@gmail.com\n */\n@NgModule({\n declarations: [],\n imports: [],\n exports: [],\n})\nexport class NgxGeocodingModule {}\n","import { InjectionToken, Provider } from \"@angular/core\";\nimport { NgxGeocodingConfig } from \"./model/ngx-geocoding-config.model\";\n\n/**\n * @author Vito Salvia - CNR IMAA geoSDI Group\n * @email vito.salvia@gmail.com\n */\n\n/**\n * La configurazione della ricerca, che **può non esserci** : in quel caso vale\n * il comportamento storico, cioè Nominatim e basta.\n */\nexport const NGX_GEOCODING_CONFIG: InjectionToken<NgxGeocodingConfig> =\n new InjectionToken<NgxGeocodingConfig>(\"NGX_GEOCODING_CONFIG\");\n\n/**\n * Dichiara da dove arrivano gli indirizzi, nei `providers` dell'applicazione :\n *\n * ```ts\n * provideNgxGeocoding({\n * sources: [\"google\", \"nominatim\"],\n * country: \"it\",\n * bias: { lat: 40.83, lon: 14.11, radiusM: 25_000 },\n * })\n * ```\n *\n * L'ordine è quello in cui le sorgenti si provano, e una che non è utilizzabile\n * si salta : la stessa riga vale quindi per il deploy che ha la chiave Google e\n * per quello che non ce l'ha.\n *\n * Chi non la chiama non cambia niente.\n */\nexport function provideNgxGeocoding(config: NgxGeocodingConfig): Provider {\n return { provide: NGX_GEOCODING_CONFIG, useValue: config };\n}","/**\n * L'SDK Maps JS dell'applicazione ospite, e l'attesa perché sia pronto.\n *\n * **Questa libreria non lo carica** : il tag lo mette in pagina chi la usa, con\n * la propria chiave —\n *\n * ```html\n * <script defer src=\"https://maps.googleapis.com/maps/api/js?key=…&libraries=places&language=it\"></script>\n * ```\n *\n * — e le ragioni perché resti così sono due : la chiave è dell'applicazione e\n * non deve passare di qui, e caricarlo una seconda volta vorrebbe dire due\n * copie dell'SDK nella stessa pagina.\n *\n * Serve però **aspettarlo** : quel tag è di norma `defer`, quindi chi cerca un\n * indirizzo subito dopo l'avvio può arrivare prima di lui.\n *\n * Della query contano due parametri : `libraries=places`, senza cui non c'è\n * niente da aspettare, e `language`, che decide la lingua delle proposte —\n * `getPlacePredictions` non ha un parametro per chiederla.\n *\n * @author Vito Salvia - CNR IMAA geoSDI Group\n * @email vito.salvia@gmail.com\n */\n\n/** Quanto si aspetta l'SDK prima di rinunciare, e ogni quanto lo si guarda. */\nconst ATTESA: { tetto_ms: number; passo_ms: number } = {\n tetto_ms: 10_000,\n passo_ms: 100,\n};\n\n/**\n * La libreria `places` dell'SDK, quel poco che se ne usa.\n *\n * Tipi **nostri** e non `@types/google.maps` : quel pacchetto diventerebbe una\n * dipendenza di chiunque usi la libreria, per due classi e una manciata di\n * campi.\n */\nexport interface LibreriaPlaces {\n /**\n * Places **(New)**, la strada che Google raccomanda dal 1° marzo 2025 —\n * `AutocompleteService` «non è disponibile per i nuovi clienti».\n *\n * **Opzionale**, e per due ragioni diverse : su un SDK più vecchio la\n * classe non c'è, e dove c'è può comunque rispondere `403` perché sotto sta\n * il prodotto **Places API (New)**, che sul progetto Cloud va abilitato a\n * parte. In tutti e due i casi si scende di un gradino.\n */\n AutocompleteSuggestion?: {\n fetchAutocompleteSuggestions(richiesta: {\n input: string;\n includedRegionCodes?: string[];\n locationBias?: CerchioSdk;\n language?: string;\n region?: string;\n }): Promise<{ suggestions?: SuggerimentoSdk[] }>;\n };\n /** Il luogo di Places (New), da cui si prendono le coordinate. */\n Place?: new (opzioni: { id: string }) => LuogoNuovoSdk;\n AutocompleteService: new () => {\n getPlacePredictions(\n richiesta: {\n input: string;\n componentRestrictions?: { country: string | string[] };\n locationBias?: CerchioSdk;\n },\n risposta: (proposte: PropostaSdk[] | null, stato: string) => void,\n ): void;\n };\n PlacesService: new (contenitore: HTMLElement) => {\n getDetails(\n richiesta: { placeId: string; fields: string[] },\n risposta: (luogo: LuogoSdk | null, stato: string) => void,\n ): void;\n };\n}\n\n/**\n * Il punto e il raggio su cui polarizzare le proposte, nella forma che l'SDK\n * accetta come `locationBias` : un oggetto, non una `Circle` da costruire, così\n * questi tipi restano dichiarazioni e non richiedono l'SDK a chi compila.\n */\nexport interface CerchioSdk {\n center: { lat: number; lng: number };\n radius: number;\n}\n\n/** Il riquadro che il `Geocoder` accetta come `bounds`. */\nexport interface RiquadroSdk {\n north: number;\n south: number;\n east: number;\n west: number;\n}\n\n/**\n * Il **Geocoder** dell'SDK, che è l'equivalente nel browser della terza strada\n * di Google : nessuna proposta incrementale, di norma un risultato solo, ma\n * **porta già le coordinate** e risponde dove Places è negata.\n */\nexport interface Geocoder {\n geocode(\n richiesta: {\n address: string;\n componentRestrictions?: { country: string | string[] };\n bounds?: RiquadroSdk;\n region?: string;\n },\n risposta: (\n risultati: RisultatoGeocoder[] | null,\n stato: string,\n ) => void,\n ): void;\n}\n\n/** Un risultato del `Geocoder`, con le coordinate dentro. */\nexport interface RisultatoGeocoder {\n place_id?: string;\n formatted_address?: string;\n geometry?: { location?: { lat(): number; lng(): number } };\n}\n\n/**\n * Una proposta di `AutocompleteSuggestion`.\n *\n * `text` non è una stringa ma un oggetto formattabile : va letto con\n * `toString()`, e scritto in un template verrebbe fuori `[object Object]`.\n */\nexport interface SuggerimentoSdk {\n placePrediction?: {\n placeId?: string;\n text?: { toString(): string };\n };\n}\n\n/**\n * Il luogo di Places (New) : nasce con l'id e si riempie con `fetchFields`,\n * che **muta l'oggetto** invece di restituire i campi — dopo l'attesa si\n * leggono da lui.\n */\nexport interface LuogoNuovoSdk {\n formattedAddress?: string | null;\n location?: { lat(): number; lng(): number } | null;\n fetchFields(richiesta: { fields: string[] }): Promise<unknown>;\n}\n\n/** Una proposta di `AutocompleteService`, che le coordinate non le porta. */\nexport interface PropostaSdk {\n place_id?: string;\n description?: string;\n}\n\n/** Il dettaglio di `PlacesService`, che invece le porta. */\nexport interface LuogoSdk {\n formatted_address?: string;\n geometry?: { location?: { lat(): number; lng(): number } };\n}\n\n/** Gli stati dell'SDK su cui si decide qualcosa. */\nexport const STATO_PLACES: {\n ok: string;\n nessuno: string;\n negato: string;\n quota: string;\n} = {\n ok: \"OK\",\n nessuno: \"ZERO_RESULTS\",\n negato: \"REQUEST_DENIED\",\n quota: \"OVER_QUERY_LIMIT\",\n};\n\ninterface FinestraConMaps extends Window {\n google?: {\n maps?: {\n places?: LibreriaPlaces;\n Geocoder?: new () => Geocoder;\n };\n };\n}\n\n/** La libreria `places` se è già in pagina, `undefined` altrimenti. */\nfunction places(): LibreriaPlaces | undefined {\n return (window as FinestraConMaps).google?.maps?.places;\n}\n\n/** Il costruttore del `Geocoder`, che sta nell'SDK di base. */\nfunction geocoder(): (new () => Geocoder) | undefined {\n return (window as FinestraConMaps).google?.maps?.Geocoder;\n}\n\n/**\n * La libreria `places`, aspettando che l'SDK finisca di caricarsi.\n *\n * Rifiuta dopo {@link ATTESA} : il chiamante ripiega sulla strada successiva,\n * perché una ricerca che non risponde mai è peggio di una che risponde meno\n * bene. Il motivo tipico di un'attesa che scade è che al tag dello script manchi\n * `libraries=places` — l'SDK c'è, ma quella libreria no.\n */\nexport function attendiPlaces(): Promise<LibreriaPlaces> {\n return attendi(places, \"la libreria 'places' (manca `libraries=places` ?)\");\n}\n\n/**\n * Il `Geocoder`, aspettando l'SDK.\n *\n * **Non vuole `libraries=places`** : sta nell'SDK di base, ed è la ragione per\n * cui regge da ultima spiaggia anche dove Places non è disponibile.\n */\nexport function attendiGeocoder(): Promise<Geocoder> {\n return attendi(geocoder, \"il Geocoder\").then(\n (costruttore: new () => Geocoder) => new costruttore(),\n );\n}\n\n/** L'attesa vera, uguale per le due parti dell'SDK. */\nfunction attendi<T>(cerca: () => T | undefined, cosa: string): Promise<T> {\n const gia: T | undefined = cerca();\n if (gia) return Promise.resolve(gia);\n\n return new Promise<T>((risolvi: (trovato: T) => void, rifiuta) => {\n const scadenza: number = Date.now() + ATTESA.tetto_ms;\n const attesa: ReturnType<typeof setInterval> = setInterval(() => {\n const pronto: T | undefined = cerca();\n if (pronto) {\n clearInterval(attesa);\n risolvi(pronto);\n return;\n }\n if (Date.now() > scadenza) {\n clearInterval(attesa);\n rifiuta(new Error(`SDK Maps senza ${cosa}`));\n }\n }, ATTESA.passo_ms);\n });\n}\n","import { Injectable, inject } from \"@angular/core\";\nimport { HttpClient } from \"@angular/common/http\";\nimport { GeocodingLocation } from \"./model/geocoding-location.model\";\nimport { Observable, Subject, from, of, throwError } from \"rxjs\";\nimport { catchError, map, switchMap, tap } from \"rxjs/operators\";\nimport {\n NgxGeocodingBias,\n NgxGeocodingConfig,\n NgxGeocodingSource,\n} from \"./model/ngx-geocoding-config.model\";\nimport { NGX_GEOCODING_CONFIG } from \"./ngx-geocoding.config\";\nimport {\n CerchioSdk,\n Geocoder,\n LibreriaPlaces,\n LuogoNuovoSdk,\n LuogoSdk,\n PropostaSdk,\n RiquadroSdk,\n RisultatoGeocoder,\n STATO_PLACES,\n SuggerimentoSdk,\n attendiGeocoder,\n attendiPlaces,\n} from \"./google-maps-sdk\";\n\n/**\n * @author Vito Salvia - CNR IMAA geoSDI Group\n * @email vito.salvia@gmail.com\n */\n\n/** Il servizio pubblico di OpenStreetMap, quando non se ne dichiara un altro. */\nconst NOMINATIM: string = \"https://nominatim.openstreetmap.org/search.php\";\n\n/** Le sorgenti da provare quando l'applicazione non dice niente. */\nconst SOLO_NOMINATIM: NgxGeocodingSource[] = [\"nominatim\"];\n\n/** Quanti metri fa un grado di latitudine, per il riquadro del Geocoder. */\nconst METRI_PER_GRADO: number = 111_320;\n\n/**\n * La ricerca di indirizzi, da una o più sorgenti.\n *\n * **Senza configurazione fa quello che ha sempre fatto** : interroga Nominatim,\n * che non vuole nessuna chiave. Google si accende con\n * `provideNgxGeocoding({ sources: [\"google\", \"nominatim\"] })`, e vuole che\n * l'applicazione abbia in pagina l'**SDK Maps** con `libraries=places`.\n *\n * **Perché l'SDK e non una chiamata a Google**, che è la cosa da sapere prima\n * di «semplificare» questo codice : delle API di Google dal browser si può\n * chiamare la sola **Places (New)**, l'unica che esponga CORS, e quel prodotto\n * va abilitato a parte sul progetto Cloud — dove non lo è, una `fetch` prende\n * `403 SERVICE_DISABLED`. **Places legacy** e **Geocoding** CORS non ce l'hanno\n * affatto, ma l'SDK le raggiunge da sé : passando da lui la ricerca funziona\n * con le abilitazioni che il progetto ha già.\n *\n * Dentro `google` c'è quindi una **cascata**, ed è la stessa che si scriverebbe\n * lato server :\n *\n * 1. **`AutocompleteSuggestion`** (Places **New**), che è la strada\n * raccomandata da Google dal 1° marzo 2025 e l'unica offerta ai progetti\n * nuovi. Sotto sta un prodotto che va **abilitato a parte** sulla console\n * Cloud : dove non lo è risponde `403`, e si scende;\n * 2. **`AutocompleteService`** (Places legacy), che dà le stesse proposte\n * incrementali. Google la dà per deprecata — «non disponibile per i nuovi\n * clienti», con dodici mesi di preavviso prima di spegnerla — ma è quella\n * che risponde sui progetti dove la New non è stata abilitata;\n * 3. **`Geocoder`**, quando nemmeno Places risponde : nessuna proposta\n * incrementale, di norma un risultato solo, ma **porta già le coordinate** e\n * sta nell'SDK di base, quindi non dipende da `libraries=places`.\n *\n * I gradini si scendono da sé e non si risalgono nella stessa sessione. Il\n * primo è in cima **anche se oggi, su un progetto senza la New, fallisce\n * sempre** : costa una richiesta negata per sessione, e il giorno in cui quel\n * prodotto viene abilitato la ricerca si sposta sulla strada giusta senza che\n * nessuno tocchi il codice.\n *\n * **Le proposte di Places non portano le coordinate**, che si chiedono per il\n * solo luogo scelto : vedi {@link resolve}, ed è il motivo per cui esiste.\n */\n@Injectable({\n providedIn: \"root\",\n})\nexport class NgxGeocodingService {\n subjectLocation = new Subject<GeocodingLocation>();\n subjectNoResults = new Subject();\n subjectRemove = new Subject();\n private http: HttpClient = inject(HttpClient);\n private config: NgxGeocodingConfig | null = inject(NGX_GEOCODING_CONFIG, {\n optional: true,\n });\n\n /**\n * Una sorgente che ha detto di no non si richiama per il resto della\n * sessione : chiave senza il prodotto abilitato, referrer fuori dalle\n * restrizioni, quota. Senza questo sarebbe una richiesta negata a ogni\n * tasto premuto.\n */\n private spente: Set<NgxGeocodingSource> = new Set<NgxGeocodingSource>();\n\n /**\n * Dentro `google`, i gradini già scesi : `AutocompleteSuggestion` (Places\n * New) e `AutocompleteService` (Places legacy). Da lì in poi si parte\n * direttamente da dove si era arrivati.\n */\n private suggestionSpenta: boolean = false;\n private placesSpenta: boolean = false;\n\n /**\n * Le proposte per quello che si sta digitando, dalla prima sorgente che\n * risponde.\n *\n * @param address il testo digitato\n */\n geocode(address: string): Observable<GeocodingLocation[]> {\n return this.daSorgenti(address, this.sorgenti());\n }\n\n /**\n * Le coordinate del luogo **scelto**, chieste solo adesso.\n *\n * Le proposte di Places arrivano senza, e risolverle tutte a ogni tasto\n * premuto vorrebbe dire una richiesta di dettaglio per proposta. Chi le ha\n * già — Nominatim le manda sempre, e il `Geocoder` pure — non paga niente e\n * si riprende il luogo così com'è, quindi **chiamarla è sempre corretto** :\n * è la riga da mettere dove si sceglie una proposta, prima di usarne `lat`\n * e `lon`.\n *\n * Fallendo restituisce il luogo com'è, senza coordinate : chi ha chiamato\n * lo sa già gestire, ed è meglio che muovere una mappa a caso.\n *\n * @param place la proposta scelta fra quelle di {@link geocode}\n */\n resolve(place: GeocodingLocation): Observable<GeocodingLocation> {\n if (!place?.place_id || (place.lat && place.lon)) return of(place);\n if (this.spente.has(\"google\")) return of(place);\n if (!this.sorgenti().includes(\"google\")) return of(place);\n\n // Lo stesso ordine delle proposte : chi le ha date sa dare anche il\n // dettaglio, e chiedere il dettaglio a Places (New) quando le proposte\n // sono arrivate dalla legacy sarebbe una richiesta negata in più.\n if (!this.suggestionSpenta) {\n return this.luogoDaSuggestion(place).pipe(\n catchError((err: unknown) => {\n this.suggestionSpenta = true;\n console.warn(\n \"[ngx-geocoding] dettaglio da Places (New) non \" +\n `riuscito, si prova la legacy — ${this.perche(err)}`,\n );\n return this.luogoDaLegacy(place);\n }),\n );\n }\n if (this.placesSpenta) return of(place);\n return this.luogoDaLegacy(place);\n }\n\n /**\n * Le coordinate con **Places (New)** : `Place` nasce con l'id e\n * `fetchFields` lo **riempie**, quindi i campi si leggono dall'oggetto\n * dopo l'attesa e non dal valore restituito.\n */\n private luogoDaSuggestion(\n place: GeocodingLocation,\n ): Observable<GeocodingLocation> {\n return from(attendiPlaces()).pipe(\n switchMap((places: LibreriaPlaces) => {\n const Luogo = places.Place;\n if (!Luogo) {\n return throwError(\n () => new Error(\"Place non c'è in questo SDK\"),\n );\n }\n\n const luogo: LuogoNuovoSdk = new Luogo({\n id: place.place_id as string,\n });\n return from(\n luogo.fetchFields({\n fields: [\"location\", \"formattedAddress\"],\n }),\n ).pipe(\n map(() => ({\n ...place,\n display_name:\n place.display_name ?? luogo.formattedAddress ?? \"\",\n lat: this.testo(luogo.location?.lat()),\n lon: this.testo(luogo.location?.lng()),\n })),\n );\n }),\n );\n }\n\n /** Le coordinate con **Places legacy**, cioè `PlacesService.getDetails`. */\n private luogoDaLegacy(\n place: GeocodingLocation,\n ): Observable<GeocodingLocation> {\n return from(attendiPlaces()).pipe(\n switchMap(\n (places: LibreriaPlaces) =>\n new Observable<GeocodingLocation>((chi) => {\n new places.PlacesService(\n document.createElement(\"div\"),\n ).getDetails(\n {\n placeId: place.place_id as string,\n fields: [\"geometry\", \"formatted_address\"],\n },\n (luogo: LuogoSdk | null, stato: string) => {\n if (stato !== STATO_PLACES.ok || !luogo) {\n chi.error(new Error(stato));\n return;\n }\n const punto = luogo.geometry?.location;\n chi.next({\n ...place,\n display_name:\n place.display_name ??\n luogo.formatted_address ??\n \"\",\n lat: this.testo(punto?.lat()),\n lon: this.testo(punto?.lng()),\n });\n chi.complete();\n },\n );\n }),\n ),\n catchError((err: unknown) => {\n console.warn(\n \"[ngx-geocoding] coordinate del luogo non risolte — \" +\n this.perche(err),\n );\n return of(place);\n }),\n );\n }\n\n /**\n * Prova le sorgenti in ordine, passando alla successiva quando una rifiuta.\n *\n * Finite le sorgenti si rilancia un errore invece di restituire un elenco\n * vuoto : «non ho trovato niente» e «non ho potuto cercare» sono due cose\n * diverse, e chi mostra la barra deve poterle distinguere.\n */\n private daSorgenti(\n address: string,\n restanti: NgxGeocodingSource[],\n ): Observable<GeocodingLocation[]> {\n const sorgente: NgxGeocodingSource | undefined = restanti[0];\n if (!sorgente) {\n return throwError(\n () => new Error(\"Nessuna sorgente di geocoding disponibile\"),\n );\n }\n\n const dopo: NgxGeocodingSource[] = restanti.slice(1);\n if (this.spente.has(sorgente)) return this.daSorgenti(address, dopo);\n\n const richiesta: Observable<GeocodingLocation[]> =\n sorgente === \"google\"\n ? this.daGoogle(address)\n : this.daNominatim(address);\n\n return richiesta.pipe(\n tap((luoghi: GeocodingLocation[]) => {\n if (luoghi.length <= 0) {\n this.subjectNoResults.next(null);\n }\n }),\n catchError((err: unknown) => {\n this.spente.add(sorgente);\n console.warn(\n `[ngx-geocoding] sorgente \"${sorgente}\" non utilizzabile, ` +\n `non la si richiede più — ${this.perche(err)}`,\n );\n return this.daSorgenti(address, dopo);\n }),\n );\n }\n\n /**\n * Nominatim, **identico a come questa libreria l'ha sempre chiamato** : è\n * il comportamento su cui contano le applicazioni che la usavano prima che\n * Google esistesse qui dentro.\n */\n private daNominatim(address: string): Observable<GeocodingLocation[]> {\n const encoded = encodeURIComponent(address);\n const base: string = this.config?.nominatimUrl ?? NOMINATIM;\n return this.http\n .get<Location>(`${base}?q=${encoded}&format=jsonv2`)\n .pipe(\n map((res: any) =>\n res.map((item: any) => ({\n display_name: item.display_name,\n lat: item.lat,\n lon: item.lon,\n place_id: item.place_id,\n })),\n ),\n );\n }\n\n /**\n * Google : le proposte di Places, e il `Geocoder` quando Places dice di no.\n *\n * `ZERO_RESULTS` **non** è un rifiuto : è una ricerca senza esiti, e\n * confonderlo con un errore farebbe scivolare al `Geocoder` — e poi fuori\n * da Google — alla prima ricerca sfortunata.\n */\n private daGoogle(address: string): Observable<GeocodingLocation[]> {\n if (this.suggestionSpenta) return this.dallaLegacy(address);\n\n return this.daSuggestion(address).pipe(\n catchError((err: unknown) => {\n this.suggestionSpenta = true;\n console.warn(\n \"[ngx-geocoding] Places (New) non utilizzabile, si prova \" +\n `quella legacy — ${this.perche(err)}`,\n );\n return this.dallaLegacy(address);\n }),\n );\n }\n\n /** Il secondo e il terzo gradino : Places legacy, poi il `Geocoder`. */\n private dallaLegacy(address: string): Observable<GeocodingLocation[]> {\n if (this.placesSpenta) return this.daGeocoder(address);\n\n return this.daPlaces(address).pipe(\n catchError((err: unknown) => {\n this.placesSpenta = true;\n console.warn(\n \"[ngx-geocoding] Places legacy non utilizzabile, si prova \" +\n `il Geocoder — ${this.perche(err)}`,\n );\n return this.daGeocoder(address);\n }),\n );\n }\n\n /**\n * Le proposte di **Places (New)**, con `AutocompleteSuggestion`.\n *\n * Due cose che non si vedono dalla firma : `text` di una proposta non è una\n * stringa ma un oggetto formattabile, e va letto con `toString()` — messo\n * in un template darebbe `[object Object]` ; e un elenco **vuoto non è un\n * errore**, è una ricerca senza esiti, quindi non fa scendere di gradino.\n *\n * Se la classe non c'è nell'SDK — versione più vecchia — si solleva subito,\n * che è il modo di scendere senza aspettare una risposta che non arriverà.\n */\n private daSuggestion(address: string): Observable<GeocodingLocation[]> {\n const paese: string | undefined = this.config?.country;\n const cerchio: CerchioSdk | undefined = this.cerchio();\n\n return from(attendiPlaces()).pipe(\n switchMap((places: LibreriaPlaces) => {\n const nuova = places.AutocompleteSuggestion;\n if (!nuova) {\n return throwError(\n () =>\n new Error(\n \"AutocompleteSuggestion non c'è in questo SDK\",\n ),\n );\n }\n\n return from(\n nuova.fetchAutocompleteSuggestions({\n input: address,\n ...(paese\n ? { includedRegionCodes: [paese], region: paese }\n : {}),\n ...(cerchio ? { locationBias: cerchio } : {}),\n }),\n ).pipe(\n map((risposta: { suggestions?: SuggerimentoSdk[] }) =>\n (risposta?.suggestions ?? [])\n .map((s: SuggerimentoSdk) => s.placePrediction)\n .filter(\n (p): p is NonNullable<typeof p> => !!p?.placeId,\n )\n .map((p) => ({\n place_id: p.placeId,\n display_name: p.text?.toString() ?? \"\",\n })),\n ),\n );\n }),\n );\n }\n\n /** Le proposte incrementali di `AutocompleteService`. */\n private daPlaces(address: string): Observable<GeocodingLocation[]> {\n const paese: string | undefined = this.config?.country;\n const cerchio: CerchioSdk | undefined = this.cerchio();\n\n return from(attendiPlaces()).pipe(\n switchMap(\n (places: LibreriaPlaces) =>\n new Observable<GeocodingLocation[]>((chi) => {\n new places.AutocompleteService().getPlacePredictions(\n {\n input: address,\n ...(paese\n ? {\n componentRestrictions: {\n country: paese,\n },\n }\n : {}),\n ...(cerchio ? { locationBias: cerchio } : {}),\n },\n (proposte: PropostaSdk[] | null, stato: string) => {\n if (stato === STATO_PLACES.nessuno) {\n chi.next([]);\n chi.complete();\n return;\n }\n if (stato !== STATO_PLACES.ok) {\n chi.error(new Error(stato));\n return;\n }\n chi.next(\n (proposte ?? [])\n .filter(\n (p: PropostaSdk) => !!p.place_id,\n )\n .map((p: PropostaSdk) => ({\n place_id: p.place_id,\n display_name: p.description ?? \"\",\n })),\n );\n chi.complete();\n },\n );\n }),\n ),\n );\n }\n\n /**\n * Il `Geocoder`, l'ultima strada di Google.\n *\n * I suoi risultati **portano già le coordinate**, quindi su questi\n * {@link resolve} non fa nessuna richiesta in più.\n */\n private daGeocoder(address: string): Observable<GeocodingLocation[]> {\n const paese: string | undefined = this.config?.country;\n const riquadro: RiquadroSdk | undefined = this.riquadro();\n\n return from(attendiGeocoder()).pipe(\n switchMap(\n (geocoder: Geocoder) =>\n new Observable<GeocodingLocation[]>((chi) => {\n geocoder.geocode(\n {\n address,\n ...(paese\n ? {\n componentRestrictions: {\n country: paese,\n },\n region: paese,\n }\n : {}),\n ...(riquadro ? { bounds: riquadro } : {}),\n },\n (\n risultati: RisultatoGeocoder[] | null,\n stato: string,\n ) => {\n if (stato === STATO_PLACES.nessuno) {\n chi.next([]);\n chi.complete();\n return;\n }\n if (stato !== STATO_PLACES.ok) {\n chi.error(new Error(stato));\n return;\n }\n chi.next(\n (risultati ?? []).map(\n (r: RisultatoGeocoder) => ({\n place_id: r.place_id,\n display_name:\n r.formatted_address ?? \"\",\n lat: this.testo(\n r.geometry?.location?.lat(),\n ),\n lon: this.testo(\n r.geometry?.location?.lng(),\n ),\n }),\n ),\n );\n chi.complete();\n },\n );\n }),\n ),\n );\n }\n\n /** Il bias come lo vuole `AutocompleteService`. */\n private cerchio(): CerchioSdk | undefined {\n const bias: NgxGeocodingBias | undefined = this.config?.bias;\n return bias\n ? {\n center: { lat: bias.lat, lng: bias.lon },\n radius: bias.radiusM,\n }\n : undefined;\n }\n\n /**\n * Il bias come lo vuole il `Geocoder`, che prende un **riquadro** e non un\n * cerchio : lo si iscrive attorno al punto. La longitudine si stringe con\n * la latitudine (`cos`), o alle nostre latitudini il riquadro verrebbe\n * largo un terzo in più del voluto.\n */\n private riquadro(): RiquadroSdk | undefined {\n const bias: NgxGeocodingBias | undefined = this.config?.bias;\n if (!bias) return undefined;\n\n const dLat: number = bias.radiusM / METRI_PER_GRADO;\n const dLon: number =\n dLat / Math.max(Math.cos((bias.lat * Math.PI) / 180), 0.01);\n return {\n north: bias.lat + dLat,\n south: bias.lat - dLat,\n east: bias.lon + dLon,\n west: bias.lon - dLon,\n };\n }\n\n /** Le sorgenti dichiarate, o quella storica. */\n private sorgenti(): NgxGeocodingSource[] {\n const dichiarate: NgxGeocodingSource[] = this.config?.sources ?? [];\n return dichiarate.length ? dichiarate : SOLO_NOMINATIM;\n }\n\n /**\n * Perché una strada ha detto di no, in una riga : dall'SDK arriva uno stato\n * (`REQUEST_DENIED` per la chiave senza il prodotto abilitato o per il\n * referrer, `OVER_QUERY_LIMIT` per la quota), da una http il corpo\n * d'errore. Senza questo il motivo resta dentro un oggetto che in console\n * va aperto, e si legge solo «si ripiega».\n */\n private perche(err: unknown): string {\n if (err instanceof Error && err.message) return err.message;\n\n const dettaglio: { status?: string; message?: string } | undefined = (\n (err as { error?: unknown })?.error as {\n error?: { status?: string; message?: string };\n }\n )?.error;\n if (!dettaglio) return \"motivo non dichiarato\";\n\n return [dettaglio.status, dettaglio.message]\n .filter((pezzo: string | undefined) => !!pezzo)\n .join(\" : \");\n }\n\n /**\n * Una coordinata come stringa, o `undefined` se non c'è.\n *\n * `String(undefined)` darebbe `\"undefined\"`, che passerebbe indenne per\n * ogni controllo di presenza e morirebbe in `Number()` — cioè una mappa\n * portata su `NaN, NaN` senza che niente lo dica.\n */\n private testo(valore: number | null | undefined): string | undefined {\n return valore === null || valore === undefined\n ? undefined\n : String(valore);\n }\n}","/**\n * @author Vito Salvia - CNR IMAA geoSDI Group\n * @email vito.salvia@gmail.com\n */\n\n/**\n * Da dove arrivano le proposte di indirizzo.\n *\n * - `google` : l'**SDK Maps JS**, che l'applicazione deve caricare con\n * `libraries=places`. Non vuole nessuna chiave qui : ce l'ha il tag dello\n * script. Dentro è **una cascata** — le proposte di Places e, quando Places\n * è negata, il `Geocoder` — perché è quello che il browser può raggiungere;\n * - `nominatim` : il servizio pubblico di OpenStreetMap, che non vuole nessuna\n * chiave. È il comportamento storico di questa libreria.\n */\nexport type NgxGeocodingSource = \"google\" | \"nominatim\";\n\n/**\n * Il punto su cui polarizzare le proposte, e con che raggio.\n *\n * È un **bias, non un filtro** : un indirizzo fuori area resta raggiungibile,\n * ma «via Roma» propone prima quella vicina. Senza, Google ordina come crede,\n * e su un nome di via comune la prima proposta è quasi sempre altrove.\n */\nexport interface NgxGeocodingBias {\n lat: number;\n lon: number;\n /** Raggio in metri. */\n radiusM: number;\n}\n\n/**\n * Come questa libreria cerca gli indirizzi.\n *\n * **Non fornirla lascia tutto com'era** : una sola sorgente, Nominatim, che è\n * quello che la libreria ha sempre fatto. Google si accende dichiarandolo in\n * {@link sources}.\n */\nexport interface NgxGeocodingConfig {\n /**\n * Le sorgenti da provare, **in ordine**. La prima che risponde vince, e\n * quella che rifiuta passa la mano alla successiva.\n *\n * Una sorgente che non è utilizzabile viene **saltata**, e non è un errore :\n * `google` senza l'SDK in pagina. È il modo in cui la stessa configurazione\n * vale per il deploy che ha la chiave e per quello che non ce l'ha.\n *\n * Default : `[\"nominatim\"]`.\n */\n sources?: NgxGeocodingSource[];\n\n /**\n * Paese a cui limitare le proposte, in due lettere (`\"it\"`). Vale per\n * `google` — Nominatim qui non è filtrato, per non cambiare quello che la\n * libreria ha sempre restituito.\n */\n country?: string;\n\n /** Dove polarizzare le proposte di `google`. Vedi {@link NgxGeocodingBias}. */\n bias?: NgxGeocodingBias;\n\n /** Il servizio Nominatim, se non quello pubblico di OpenStreetMap. */\n nominatimUrl?: string;\n}","/*\n * Public API Surface of ngx-geocoding\n */\n\nexport * from \"./lib/ngx-geocoding.module\";\nexport * from \"./lib/ngx-geocoding.service\";\nexport * from \"./lib/ngx-geocoding.config\";\nexport * from \"./lib/model/geocoding-location.model\";\nexport * from \"./lib/model/ngx-geocoding-config.model\";\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"geosdi-ngx-geocoding.mjs","names":[],"sources":["../../../../projects/geosdi/support/ngx-geocoding/src/lib/ngx-geocoding.module.ts","../../../../projects/geosdi/support/ngx-geocoding/src/lib/ngx-geocoding.config.ts","../../../../projects/geosdi/support/ngx-geocoding/src/lib/google-maps-sdk.ts","../../../../projects/geosdi/support/ngx-geocoding/src/lib/ngx-geocoding.service.ts"],"sourcesContent":["import { NgModule } from \"@angular/core\";\n\n/**\n * @author Vito Salvia - CNR IMAA geoSDI Group\n * @email vito.salvia@gmail.com\n */\n@NgModule({\n declarations: [],\n imports: [],\n exports: [],\n})\nexport class NgxGeocodingModule {}\n","import { InjectionToken, Provider } from \"@angular/core\";\nimport { NgxGeocodingConfig } from \"./model/ngx-geocoding-config.model\";\n\n/**\n * @author Vito Salvia - CNR IMAA geoSDI Group\n * @email vito.salvia@gmail.com\n */\n\n/**\n * La configurazione della ricerca, che **può non esserci** : in quel caso vale\n * il comportamento storico, cioè Nominatim e basta.\n */\nexport const NGX_GEOCODING_CONFIG: InjectionToken<NgxGeocodingConfig> =\n new InjectionToken<NgxGeocodingConfig>(\"NGX_GEOCODING_CONFIG\");\n\n/**\n * Dichiara da dove arrivano gli indirizzi, nei `providers` dell'applicazione :\n *\n * ```ts\n * provideNgxGeocoding({\n * sources: [\"google\", \"nominatim\"],\n * country: \"it\",\n * bias: { lat: 40.83, lon: 14.11, radiusM: 25_000 },\n * })\n * ```\n *\n * L'ordine è quello in cui le sorgenti si provano, e una che non è utilizzabile\n * si salta : la stessa riga vale quindi per il deploy che ha la chiave Google e\n * per quello che non ce l'ha.\n *\n * Chi non la chiama non cambia niente.\n */\nexport function provideNgxGeocoding(config: NgxGeocodingConfig): Provider {\n return { provide: NGX_GEOCODING_CONFIG, useValue: config };\n}\n","/**\n * L'SDK Maps JS dell'applicazione ospite, e l'attesa perché sia pronto.\n *\n * **Questa libreria non lo carica** : il tag lo mette in pagina chi la usa, con\n * la propria chiave —\n *\n * ```html\n * <script defer src=\"https://maps.googleapis.com/maps/api/js?key=…&libraries=places&language=it\"></script>\n * ```\n *\n * — e le ragioni perché resti così sono due : la chiave è dell'applicazione e\n * non deve passare di qui, e caricarlo una seconda volta vorrebbe dire due\n * copie dell'SDK nella stessa pagina.\n *\n * Serve però **aspettarlo** : quel tag è di norma `defer`, quindi chi cerca un\n * indirizzo subito dopo l'avvio può arrivare prima di lui.\n *\n * Della query contano due parametri : `libraries=places`, senza cui non c'è\n * niente da aspettare, e `language`, che decide la lingua delle proposte —\n * `getPlacePredictions` non ha un parametro per chiederla.\n *\n * @author Vito Salvia - CNR IMAA geoSDI Group\n * @email vito.salvia@gmail.com\n */\n\n/** Quanto si aspetta l'SDK prima di rinunciare, e ogni quanto lo si guarda. */\nconst ATTESA: { tetto_ms: number; passo_ms: number } = {\n tetto_ms: 10_000,\n passo_ms: 100,\n};\n\n/**\n * La libreria `places` dell'SDK, quel poco che se ne usa.\n *\n * Tipi **nostri** e non `@types/google.maps` : quel pacchetto diventerebbe una\n * dipendenza di chiunque usi la libreria, per due classi e una manciata di\n * campi.\n */\nexport interface LibreriaPlaces {\n /**\n * Places **(New)**, la strada che Google raccomanda dal 1° marzo 2025 —\n * `AutocompleteService` «non è disponibile per i nuovi clienti».\n *\n * **Opzionale**, e per due ragioni diverse : su un SDK più vecchio la\n * classe non c'è, e dove c'è può comunque rispondere `403` perché sotto sta\n * il prodotto **Places API (New)**, che sul progetto Cloud va abilitato a\n * parte. In tutti e due i casi si scende di un gradino.\n */\n AutocompleteSuggestion?: {\n fetchAutocompleteSuggestions(richiesta: {\n input: string;\n includedRegionCodes?: string[];\n locationBias?: CerchioSdk;\n language?: string;\n region?: string;\n }): Promise<{ suggestions?: SuggerimentoSdk[] }>;\n };\n /** Il luogo di Places (New), da cui si prendono le coordinate. */\n Place?: new (opzioni: { id: string }) => LuogoNuovoSdk;\n AutocompleteService: new () => {\n getPlacePredictions(\n richiesta: {\n input: string;\n componentRestrictions?: { country: string | string[] };\n locationBias?: CerchioSdk;\n },\n risposta: (proposte: PropostaSdk[] | null, stato: string) => void,\n ): void;\n };\n PlacesService: new (contenitore: HTMLElement) => {\n getDetails(\n richiesta: { placeId: string; fields: string[] },\n risposta: (luogo: LuogoSdk | null, stato: string) => void,\n ): void;\n };\n}\n\n/**\n * Il punto e il raggio su cui polarizzare le proposte, nella forma che l'SDK\n * accetta come `locationBias` : un oggetto, non una `Circle` da costruire, così\n * questi tipi restano dichiarazioni e non richiedono l'SDK a chi compila.\n */\nexport interface CerchioSdk {\n center: { lat: number; lng: number };\n radius: number;\n}\n\n/** Il riquadro che il `Geocoder` accetta come `bounds`. */\nexport interface RiquadroSdk {\n north: number;\n south: number;\n east: number;\n west: number;\n}\n\n/**\n * Il **Geocoder** dell'SDK, che è l'equivalente nel browser della terza strada\n * di Google : nessuna proposta incrementale, di norma un risultato solo, ma\n * **porta già le coordinate** e risponde dove Places è negata.\n */\nexport interface Geocoder {\n geocode(\n richiesta: {\n address: string;\n componentRestrictions?: { country: string | string[] };\n bounds?: RiquadroSdk;\n region?: string;\n },\n risposta: (\n risultati: RisultatoGeocoder[] | null,\n stato: string,\n ) => void,\n ): void;\n}\n\n/** Un risultato del `Geocoder`, con le coordinate dentro. */\nexport interface RisultatoGeocoder {\n place_id?: string;\n formatted_address?: string;\n geometry?: { location?: { lat(): number; lng(): number } };\n}\n\n/**\n * Una proposta di `AutocompleteSuggestion`.\n *\n * `text` non è una stringa ma un oggetto formattabile : va letto con\n * `toString()`, e scritto in un template verrebbe fuori `[object Object]`.\n */\nexport interface SuggerimentoSdk {\n placePrediction?: {\n placeId?: string;\n text?: { toString(): string };\n };\n}\n\n/**\n * Il luogo di Places (New) : nasce con l'id e si riempie con `fetchFields`,\n * che **muta l'oggetto** invece di restituire i campi — dopo l'attesa si\n * leggono da lui.\n */\nexport interface LuogoNuovoSdk {\n formattedAddress?: string | null;\n location?: { lat(): number; lng(): number } | null;\n fetchFields(richiesta: { fields: string[] }): Promise<unknown>;\n}\n\n/** Una proposta di `AutocompleteService`, che le coordinate non le porta. */\nexport interface PropostaSdk {\n place_id?: string;\n description?: string;\n}\n\n/** Il dettaglio di `PlacesService`, che invece le porta. */\nexport interface LuogoSdk {\n formatted_address?: string;\n geometry?: { location?: { lat(): number; lng(): number } };\n}\n\n/** Gli stati dell'SDK su cui si decide qualcosa. */\nexport const STATO_PLACES: {\n ok: string;\n nessuno: string;\n negato: string;\n quota: string;\n} = {\n ok: \"OK\",\n nessuno: \"ZERO_RESULTS\",\n negato: \"REQUEST_DENIED\",\n quota: \"OVER_QUERY_LIMIT\",\n};\n\ninterface FinestraConMaps extends Window {\n google?: {\n maps?: {\n places?: LibreriaPlaces;\n Geocoder?: new () => Geocoder;\n };\n };\n}\n\n/** La libreria `places` se è già in pagina, `undefined` altrimenti. */\nfunction places(): LibreriaPlaces | undefined {\n return (window as FinestraConMaps).google?.maps?.places;\n}\n\n/** Il costruttore del `Geocoder`, che sta nell'SDK di base. */\nfunction geocoder(): (new () => Geocoder) | undefined {\n return (window as FinestraConMaps).google?.maps?.Geocoder;\n}\n\n/**\n * La libreria `places`, aspettando che l'SDK finisca di caricarsi.\n *\n * Rifiuta dopo {@link ATTESA} : il chiamante ripiega sulla strada successiva,\n * perché una ricerca che non risponde mai è peggio di una che risponde meno\n * bene. Il motivo tipico di un'attesa che scade è che al tag dello script manchi\n * `libraries=places` — l'SDK c'è, ma quella libreria no.\n */\nexport function attendiPlaces(): Promise<LibreriaPlaces> {\n return attendi(places, \"la libreria 'places' (manca `libraries=places` ?)\");\n}\n\n/**\n * Il `Geocoder`, aspettando l'SDK.\n *\n * **Non vuole `libraries=places`** : sta nell'SDK di base, ed è la ragione per\n * cui regge da ultima spiaggia anche dove Places non è disponibile.\n */\nexport function attendiGeocoder(): Promise<Geocoder> {\n return attendi(geocoder, \"il Geocoder\").then(\n (costruttore: new () => Geocoder) => new costruttore(),\n );\n}\n\n/** L'attesa vera, uguale per le due parti dell'SDK. */\nfunction attendi<T>(cerca: () => T | undefined, cosa: string): Promise<T> {\n const gia: T | undefined = cerca();\n if (gia) return Promise.resolve(gia);\n\n return new Promise<T>((risolvi: (trovato: T) => void, rifiuta) => {\n const scadenza: number = Date.now() + ATTESA.tetto_ms;\n const attesa: ReturnType<typeof setInterval> = setInterval(() => {\n const pronto: T | undefined = cerca();\n if (pronto) {\n clearInterval(attesa);\n risolvi(pronto);\n return;\n }\n if (Date.now() > scadenza) {\n clearInterval(attesa);\n rifiuta(new Error(`SDK Maps senza ${cosa}`));\n }\n }, ATTESA.passo_ms);\n });\n}\n","import { Injectable, inject } from \"@angular/core\";\nimport { HttpClient } from \"@angular/common/http\";\nimport { GeocodingLocation } from \"./model/geocoding-location.model\";\nimport { Observable, Subject, from, of, throwError } from \"rxjs\";\nimport { catchError, map, switchMap, tap } from \"rxjs/operators\";\nimport {\n NgxGeocodingBias,\n NgxGeocodingConfig,\n NgxGeocodingSource,\n} from \"./model/ngx-geocoding-config.model\";\nimport { NGX_GEOCODING_CONFIG } from \"./ngx-geocoding.config\";\nimport {\n CerchioSdk,\n Geocoder,\n LibreriaPlaces,\n LuogoNuovoSdk,\n LuogoSdk,\n PropostaSdk,\n RiquadroSdk,\n RisultatoGeocoder,\n STATO_PLACES,\n SuggerimentoSdk,\n attendiGeocoder,\n attendiPlaces,\n} from \"./google-maps-sdk\";\n\n/**\n * @author Vito Salvia - CNR IMAA geoSDI Group\n * @email vito.salvia@gmail.com\n */\n\n/** Il servizio pubblico di OpenStreetMap, quando non se ne dichiara un altro. */\nconst NOMINATIM: string = \"https://nominatim.openstreetmap.org/search.php\";\n\n/** Le sorgenti da provare quando l'applicazione non dice niente. */\nconst SOLO_NOMINATIM: NgxGeocodingSource[] = [\"nominatim\"];\n\n/** Quanti metri fa un grado di latitudine, per il riquadro del Geocoder. */\nconst METRI_PER_GRADO: number = 111_320;\n\n/**\n * La ricerca di indirizzi, da una o più sorgenti.\n *\n * **Senza configurazione fa quello che ha sempre fatto** : interroga Nominatim,\n * che non vuole nessuna chiave. Google si accende con\n * `provideNgxGeocoding({ sources: [\"google\", \"nominatim\"] })`, e vuole che\n * l'applicazione abbia in pagina l'**SDK Maps** con `libraries=places`.\n *\n * **Perché l'SDK e non una chiamata a Google**, che è la cosa da sapere prima\n * di «semplificare» questo codice : delle API di Google dal browser si può\n * chiamare la sola **Places (New)**, l'unica che esponga CORS, e quel prodotto\n * va abilitato a parte sul progetto Cloud — dove non lo è, una `fetch` prende\n * `403 SERVICE_DISABLED`. **Places legacy** e **Geocoding** CORS non ce l'hanno\n * affatto, ma l'SDK le raggiunge da sé : passando da lui la ricerca funziona\n * con le abilitazioni che il progetto ha già.\n *\n * Dentro `google` c'è quindi una **cascata**, ed è la stessa che si scriverebbe\n * lato server :\n *\n * 1. **`AutocompleteSuggestion`** (Places **New**), che è la strada\n * raccomandata da Google dal 1° marzo 2025 e l'unica offerta ai progetti\n * nuovi. Sotto sta un prodotto che va **abilitato a parte** sulla console\n * Cloud : dove non lo è risponde `403`, e si scende;\n * 2. **`AutocompleteService`** (Places legacy), che dà le stesse proposte\n * incrementali. Google la dà per deprecata — «non disponibile per i nuovi\n * clienti», con dodici mesi di preavviso prima di spegnerla — ma è quella\n * che risponde sui progetti dove la New non è stata abilitata;\n * 3. **`Geocoder`**, quando nemmeno Places risponde : nessuna proposta\n * incrementale, di norma un risultato solo, ma **porta già le coordinate** e\n * sta nell'SDK di base, quindi non dipende da `libraries=places`.\n *\n * I gradini si scendono da sé e non si risalgono nella stessa sessione. Il\n * primo è in cima **anche se oggi, su un progetto senza la New, fallisce\n * sempre** : costa una richiesta negata per sessione, e il giorno in cui quel\n * prodotto viene abilitato la ricerca si sposta sulla strada giusta senza che\n * nessuno tocchi il codice.\n *\n * **Le proposte di Places non portano le coordinate**, che si chiedono per il\n * solo luogo scelto : vedi {@link resolve}, ed è il motivo per cui esiste.\n */\n@Injectable({\n providedIn: \"root\",\n})\nexport class NgxGeocodingService {\n subjectLocation = new Subject<GeocodingLocation>();\n subjectNoResults = new Subject();\n subjectRemove = new Subject();\n private http: HttpClient = inject(HttpClient);\n private config: NgxGeocodingConfig | null = inject(NGX_GEOCODING_CONFIG, {\n optional: true,\n });\n\n /**\n * Una sorgente che ha detto di no non si richiama per il resto della\n * sessione : chiave senza il prodotto abilitato, referrer fuori dalle\n * restrizioni, quota. Senza questo sarebbe una richiesta negata a ogni\n * tasto premuto.\n */\n private spente: Set<NgxGeocodingSource> = new Set<NgxGeocodingSource>();\n\n /**\n * Dentro `google`, i gradini già scesi : `AutocompleteSuggestion` (Places\n * New) e `AutocompleteService` (Places legacy). Da lì in poi si parte\n * direttamente da dove si era arrivati.\n */\n private suggestionSpenta: boolean = false;\n private placesSpenta: boolean = false;\n\n /**\n * Le proposte per quello che si sta digitando, dalla prima sorgente che\n * risponde.\n *\n * @param address il testo digitato\n */\n geocode(address: string): Observable<GeocodingLocation[]> {\n return this.daSorgenti(address, this.sorgenti());\n }\n\n /**\n * Le coordinate del luogo **scelto**, chieste solo adesso.\n *\n * Le proposte di Places arrivano senza, e risolverle tutte a ogni tasto\n * premuto vorrebbe dire una richiesta di dettaglio per proposta. Chi le ha\n * già — Nominatim le manda sempre, e il `Geocoder` pure — non paga niente e\n * si riprende il luogo così com'è, quindi **chiamarla è sempre corretto** :\n * è la riga da mettere dove si sceglie una proposta, prima di usarne `lat`\n * e `lon`.\n *\n * Fallendo restituisce il luogo com'è, senza coordinate : chi ha chiamato\n * lo sa già gestire, ed è meglio che muovere una mappa a caso.\n *\n * @param place la proposta scelta fra quelle di {@link geocode}\n */\n resolve(place: GeocodingLocation): Observable<GeocodingLocation> {\n if (!place?.place_id || (place.lat && place.lon)) return of(place);\n if (this.spente.has(\"google\")) return of(place);\n if (!this.sorgenti().includes(\"google\")) return of(place);\n\n // Lo stesso ordine delle proposte : chi le ha date sa dare anche il\n // dettaglio, e chiedere il dettaglio a Places (New) quando le proposte\n // sono arrivate dalla legacy sarebbe una richiesta negata in più.\n if (!this.suggestionSpenta) {\n return this.luogoDaSuggestion(place).pipe(\n catchError((err: unknown) => {\n this.suggestionSpenta = true;\n console.warn(\n \"[ngx-geocoding] dettaglio da Places (New) non \" +\n `riuscito, si prova la legacy — ${this.perche(err)}`,\n );\n return this.luogoDaLegacy(place);\n }),\n );\n }\n if (this.placesSpenta) return of(place);\n return this.luogoDaLegacy(place);\n }\n\n /**\n * Le coordinate con **Places (New)** : `Place` nasce con l'id e\n * `fetchFields` lo **riempie**, quindi i campi si leggono dall'oggetto\n * dopo l'attesa e non dal valore restituito.\n */\n private luogoDaSuggestion(\n place: GeocodingLocation,\n ): Observable<GeocodingLocation> {\n return from(attendiPlaces()).pipe(\n switchMap((places: LibreriaPlaces) => {\n const Luogo = places.Place;\n if (!Luogo) {\n return throwError(\n () => new Error(\"Place non c'è in questo SDK\"),\n );\n }\n\n const luogo: LuogoNuovoSdk = new Luogo({\n id: place.place_id as string,\n });\n return from(\n luogo.fetchFields({\n fields: [\"location\", \"formattedAddress\"],\n }),\n ).pipe(\n map(() => ({\n ...place,\n display_name:\n place.display_name ?? luogo.formattedAddress ?? \"\",\n lat: this.testo(luogo.location?.lat()),\n lon: this.testo(luogo.location?.lng()),\n })),\n );\n }),\n );\n }\n\n /** Le coordinate con **Places legacy**, cioè `PlacesService.getDetails`. */\n private luogoDaLegacy(\n place: GeocodingLocation,\n ): Observable<GeocodingLocation> {\n return from(attendiPlaces()).pipe(\n switchMap(\n (places: LibreriaPlaces) =>\n new Observable<GeocodingLocation>((chi) => {\n new places.PlacesService(\n document.createElement(\"div\"),\n ).getDetails(\n {\n placeId: place.place_id as string,\n fields: [\"geometry\", \"formatted_address\"],\n },\n (luogo: LuogoSdk | null, stato: string) => {\n if (stato !== STATO_PLACES.ok || !luogo) {\n chi.error(new Error(stato));\n return;\n }\n const punto = luogo.geometry?.location;\n chi.next({\n ...place,\n display_name:\n place.display_name ??\n luogo.formatted_address ??\n \"\",\n lat: this.testo(punto?.lat()),\n lon: this.testo(punto?.lng()),\n });\n chi.complete();\n },\n );\n }),\n ),\n catchError((err: unknown) => {\n console.warn(\n \"[ngx-geocoding] coordinate del luogo non risolte — \" +\n this.perche(err),\n );\n return of(place);\n }),\n );\n }\n\n /**\n * Prova le sorgenti in ordine, passando alla successiva quando una rifiuta.\n *\n * Finite le sorgenti si rilancia un errore invece di restituire un elenco\n * vuoto : «non ho trovato niente» e «non ho potuto cercare» sono due cose\n * diverse, e chi mostra la barra deve poterle distinguere.\n */\n private daSorgenti(\n address: string,\n restanti: NgxGeocodingSource[],\n ): Observable<GeocodingLocation[]> {\n const sorgente: NgxGeocodingSource | undefined = restanti[0];\n if (!sorgente) {\n return throwError(\n () => new Error(\"Nessuna sorgente di geocoding disponibile\"),\n );\n }\n\n const dopo: NgxGeocodingSource[] = restanti.slice(1);\n if (this.spente.has(sorgente)) return this.daSorgenti(address, dopo);\n\n const richiesta: Observable<GeocodingLocation[]> =\n sorgente === \"google\"\n ? this.daGoogle(address)\n : this.daNominatim(address);\n\n return richiesta.pipe(\n tap((luoghi: GeocodingLocation[]) => {\n if (luoghi.length <= 0) {\n this.subjectNoResults.next(null);\n }\n }),\n catchError((err: unknown) => {\n this.spente.add(sorgente);\n console.warn(\n `[ngx-geocoding] sorgente \"${sorgente}\" non utilizzabile, ` +\n `non la si richiede più — ${this.perche(err)}`,\n );\n return this.daSorgenti(address, dopo);\n }),\n );\n }\n\n /**\n * Nominatim, **identico a come questa libreria l'ha sempre chiamato** : è\n * il comportamento su cui contano le applicazioni che la usavano prima che\n * Google esistesse qui dentro.\n */\n private daNominatim(address: string): Observable<GeocodingLocation[]> {\n const encoded = encodeURIComponent(address);\n const base: string = this.config?.nominatimUrl ?? NOMINATIM;\n return this.http\n .get<Location>(`${base}?q=${encoded}&format=jsonv2`)\n .pipe(\n map((res: any) =>\n res.map((item: any) => ({\n display_name: item.display_name,\n lat: item.lat,\n lon: item.lon,\n place_id: item.place_id,\n })),\n ),\n );\n }\n\n /**\n * Google : le proposte di Places, e il `Geocoder` quando Places dice di no.\n *\n * `ZERO_RESULTS` **non** è un rifiuto : è una ricerca senza esiti, e\n * confonderlo con un errore farebbe scivolare al `Geocoder` — e poi fuori\n * da Google — alla prima ricerca sfortunata.\n */\n private daGoogle(address: string): Observable<GeocodingLocation[]> {\n if (this.suggestionSpenta) return this.dallaLegacy(address);\n\n return this.daSuggestion(address).pipe(\n catchError((err: unknown) => {\n this.suggestionSpenta = true;\n console.warn(\n \"[ngx-geocoding] Places (New) non utilizzabile, si prova \" +\n `quella legacy — ${this.perche(err)}`,\n );\n return this.dallaLegacy(address);\n }),\n );\n }\n\n /** Il secondo e il terzo gradino : Places legacy, poi il `Geocoder`. */\n private dallaLegacy(address: string): Observable<GeocodingLocation[]> {\n if (this.placesSpenta) return this.daGeocoder(address);\n\n return this.daPlaces(address).pipe(\n catchError((err: unknown) => {\n this.placesSpenta = true;\n console.warn(\n \"[ngx-geocoding] Places legacy non utilizzabile, si prova \" +\n `il Geocoder — ${this.perche(err)}`,\n );\n return this.daGeocoder(address);\n }),\n );\n }\n\n /**\n * Le proposte di **Places (New)**, con `AutocompleteSuggestion`.\n *\n * Due cose che non si vedono dalla firma : `text` di una proposta non è una\n * stringa ma un oggetto formattabile, e va letto con `toString()` — messo\n * in un template darebbe `[object Object]` ; e un elenco **vuoto non è un\n * errore**, è una ricerca senza esiti, quindi non fa scendere di gradino.\n *\n * Se la classe non c'è nell'SDK — versione più vecchia — si solleva subito,\n * che è il modo di scendere senza aspettare una risposta che non arriverà.\n */\n private daSuggestion(address: string): Observable<GeocodingLocation[]> {\n const paese: string | undefined = this.config?.country;\n const cerchio: CerchioSdk | undefined = this.cerchio();\n\n return from(attendiPlaces()).pipe(\n switchMap((places: LibreriaPlaces) => {\n const nuova = places.AutocompleteSuggestion;\n if (!nuova) {\n return throwError(\n () =>\n new Error(\n \"AutocompleteSuggestion non c'è in questo SDK\",\n ),\n );\n }\n\n return from(\n nuova.fetchAutocompleteSuggestions({\n input: address,\n ...(paese\n ? { includedRegionCodes: [paese], region: paese }\n : {}),\n ...(cerchio ? { locationBias: cerchio } : {}),\n }),\n ).pipe(\n map((risposta: { suggestions?: SuggerimentoSdk[] }) =>\n (risposta?.suggestions ?? [])\n .map((s: SuggerimentoSdk) => s.placePrediction)\n .filter(\n (p): p is NonNullable<typeof p> => !!p?.placeId,\n )\n .map((p) => ({\n place_id: p.placeId,\n display_name: p.text?.toString() ?? \"\",\n })),\n ),\n );\n }),\n );\n }\n\n /** Le proposte incrementali di `AutocompleteService`. */\n private daPlaces(address: string): Observable<GeocodingLocation[]> {\n const paese: string | undefined = this.config?.country;\n const cerchio: CerchioSdk | undefined = this.cerchio();\n\n return from(attendiPlaces()).pipe(\n switchMap(\n (places: LibreriaPlaces) =>\n new Observable<GeocodingLocation[]>((chi) => {\n new places.AutocompleteService().getPlacePredictions(\n {\n input: address,\n ...(paese\n ? {\n componentRestrictions: {\n country: paese,\n },\n }\n : {}),\n ...(cerchio ? { locationBias: cerchio } : {}),\n },\n (proposte: PropostaSdk[] | null, stato: string) => {\n if (stato === STATO_PLACES.nessuno) {\n chi.next([]);\n chi.complete();\n return;\n }\n if (stato !== STATO_PLACES.ok) {\n chi.error(new Error(stato));\n return;\n }\n chi.next(\n (proposte ?? [])\n .filter(\n (p: PropostaSdk) => !!p.place_id,\n )\n .map((p: PropostaSdk) => ({\n place_id: p.place_id,\n display_name: p.description ?? \"\",\n })),\n );\n chi.complete();\n },\n );\n }),\n ),\n );\n }\n\n /**\n * Il `Geocoder`, l'ultima strada di Google.\n *\n * I suoi risultati **portano già le coordinate**, quindi su questi\n * {@link resolve} non fa nessuna richiesta in più.\n */\n private daGeocoder(address: string): Observable<GeocodingLocation[]> {\n const paese: string | undefined = this.config?.country;\n const riquadro: RiquadroSdk | undefined = this.riquadro();\n\n return from(attendiGeocoder()).pipe(\n switchMap(\n (geocoder: Geocoder) =>\n new Observable<GeocodingLocation[]>((chi) => {\n geocoder.geocode(\n {\n address,\n ...(paese\n ? {\n componentRestrictions: {\n country: paese,\n },\n region: paese,\n }\n : {}),\n ...(riquadro ? { bounds: riquadro } : {}),\n },\n (\n risultati: RisultatoGeocoder[] | null,\n stato: string,\n ) => {\n if (stato === STATO_PLACES.nessuno) {\n chi.next([]);\n chi.complete();\n return;\n }\n if (stato !== STATO_PLACES.ok) {\n chi.error(new Error(stato));\n return;\n }\n chi.next(\n (risultati ?? []).map(\n (r: RisultatoGeocoder) => ({\n place_id: r.place_id,\n display_name:\n r.formatted_address ?? \"\",\n lat: this.testo(\n r.geometry?.location?.lat(),\n ),\n lon: this.testo(\n r.geometry?.location?.lng(),\n ),\n }),\n ),\n );\n chi.complete();\n },\n );\n }),\n ),\n );\n }\n\n /** Il bias come lo vuole `AutocompleteService`. */\n private cerchio(): CerchioSdk | undefined {\n const bias: NgxGeocodingBias | undefined = this.config?.bias;\n return bias\n ? {\n center: { lat: bias.lat, lng: bias.lon },\n radius: bias.radiusM,\n }\n : undefined;\n }\n\n /**\n * Il bias come lo vuole il `Geocoder`, che prende un **riquadro** e non un\n * cerchio : lo si iscrive attorno al punto. La longitudine si stringe con\n * la latitudine (`cos`), o alle nostre latitudini il riquadro verrebbe\n * largo un terzo in più del voluto.\n */\n private riquadro(): RiquadroSdk | undefined {\n const bias: NgxGeocodingBias | undefined = this.config?.bias;\n if (!bias) return undefined;\n\n const dLat: number = bias.radiusM / METRI_PER_GRADO;\n const dLon: number =\n dLat / Math.max(Math.cos((bias.lat * Math.PI) / 180), 0.01);\n return {\n north: bias.lat + dLat,\n south: bias.lat - dLat,\n east: bias.lon + dLon,\n west: bias.lon - dLon,\n };\n }\n\n /** Le sorgenti dichiarate, o quella storica. */\n private sorgenti(): NgxGeocodingSource[] {\n const dichiarate: NgxGeocodingSource[] = this.config?.sources ?? [];\n return dichiarate.length ? dichiarate : SOLO_NOMINATIM;\n }\n\n /**\n * Perché una strada ha detto di no, in una riga : dall'SDK arriva uno stato\n * (`REQUEST_DENIED` per la chiave senza il prodotto abilitato o per il\n * referrer, `OVER_QUERY_LIMIT` per la quota), da una http il corpo\n * d'errore. Senza questo il motivo resta dentro un oggetto che in console\n * va aperto, e si legge solo «si ripiega».\n */\n private perche(err: unknown): string {\n if (err instanceof Error && err.message) return err.message;\n\n const dettaglio: { status?: string; message?: string } | undefined = (\n (err as { error?: unknown })?.error as {\n error?: { status?: string; message?: string };\n }\n )?.error;\n if (!dettaglio) return \"motivo non dichiarato\";\n\n return [dettaglio.status, dettaglio.message]\n .filter((pezzo: string | undefined) => !!pezzo)\n .join(\" : \");\n }\n\n /**\n * Una coordinata come stringa, o `undefined` se non c'è.\n *\n * `String(undefined)` darebbe `\"undefined\"`, che passerebbe indenne per\n * ogni controllo di presenza e morirebbe in `Number()` — cioè una mappa\n * portata su `NaN, NaN` senza che niente lo dica.\n */\n private testo(valore: number | null | undefined): string | undefined {\n return valore === null || valore === undefined\n ? undefined\n : String(valore);\n }\n}\n"],"mappings":";;;;;AAWA,IAAa,qBAAb,MAAa,mBAAkB;CAAlB;EAAA,KAAA,OAAA,GAAA,mBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAAkB,MAAA,CAAA;GAAA,QAAA,GAAA,gBAAA;EAAA,CAAA;CAAA;CAAlB;EAAA,KAAA,OAAA,GAAA,oBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;EAAkB,CAAA;CAAA;CAAlB;EAAA,KAAA,OAAA,GAAA,oBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;EAAkB,CAAA;CAAA;;AAAlB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAkB,YAAA,CAAA;EAL9B,MAAA;EAAS,MAAA,CAAA;GACN,cAAc,CAAA;GACd,SAAS,CAAA;GACT,SAAS,CAAA;EACZ,CAAA;;;ACED,MAAa,uBACT,IAAI,eAAmC,sBAAsB;AAmBjE,SAAgB,oBAAoB,QAA0B;CAC1D,OAAO;EAAE,SAAS;EAAsB,UAAU;CAAM;AAC5D;ACRA,MAAM,SAAiD;CACnD,UAAU;CACV,UAAU;AACb;AAkID,MAAa,eAKT;CACA,IAAI;CACJ,SAAS;CACT,QAAQ;CACR,OAAO;AACV;AAYD,SAAS,SAAM;CACX,OAAQ,OAA2B,QAAQ,MAAM;AACrD;AAGA,SAAS,WAAQ;CACb,OAAQ,OAA2B,QAAQ,MAAM;AACrD;AAUA,SAAgB,gBAAa;CACzB,OAAO,QAAQ,QAAQ,mDAAmD;AAC9E;AAQA,SAAgB,kBAAe;CAC3B,OAAO,QAAQ,UAAU,aAAa,CAAC,CAAC,MACnC,gBAAoC,IAAI,YAAW,CAAE;AAE9D;AAGA,SAAS,QAAW,OAA4B,MAAY;CACxD,MAAM,MAAqB,MAAK;CAChC,IAAI,KAAK,OAAO,QAAQ,QAAQ,GAAG;CAEnC,OAAO,IAAI,SAAY,SAA+B,YAAW;EAC7D,MAAM,WAAmB,KAAK,IAAG,IAAK,OAAO;EAC7C,MAAM,SAAyC,kBAAiB;GAC5D,MAAM,SAAwB,MAAK;GACnC,IAAI,QAAQ;IACR,cAAc,MAAM;IACpB,QAAQ,MAAM;IACd;GACJ;GACA,IAAI,KAAK,IAAG,IAAK,UAAU;IACvB,cAAc,MAAM;IACpB,wBAAQ,IAAI,MAAM,kBAAkB,MAAM,CAAC;GAC/C;EACJ,GAAG,OAAO,QAAQ;CACtB,CAAC;AACL;AC1MA,MAAM,YAAoB;AAG1B,MAAM,iBAAuC,CAAC,WAAW;AAGzD,MAAM,kBAA0B;AA6ChC,IAAa,sBAAb,MAAa,oBAAmB;CAHhC,cAAA;EAII,KAAA,kBAAkB,IAAI,QAAO;EAC7B,KAAA,mBAAmB,IAAI,QAAO;EAC9B,KAAA,gBAAgB,IAAI,QAAO;EACnB,KAAA,OAAmB,OAAO,UAAU;EACpC,KAAA,SAAoC,OAAO,sBAAsB,EACrE,UAAU,KACb,CAAA;EAQO,KAAA,yBAAkC,IAAI,IAAG;EAOzC,KAAA,mBAA4B;EAC5B,KAAA,eAAwB;CAwdnC;CAhdG,QAAQ,SAAe;EACnB,OAAO,KAAK,WAAW,SAAS,KAAK,SAAQ,CAAE;CACnD;CAiBA,QAAQ,OAAwB;EAC5B,IAAI,CAAC,OAAO,YAAa,MAAM,OAAO,MAAM,KAAM,OAAO,GAAG,KAAK;EACjE,IAAI,KAAK,OAAO,IAAI,QAAQ,GAAG,OAAO,GAAG,KAAK;EAC9C,IAAI,CAAC,KAAK,SAAQ,CAAE,CAAC,SAAS,QAAQ,GAAG,OAAO,GAAG,KAAK;EAKxD,IAAI,CAAC,KAAK,kBACN,OAAO,KAAK,kBAAkB,KAAK,CAAC,CAAC,KACjC,YAAY,QAAgB;GACxB,KAAK,mBAAmB;GACxB,QAAQ,KACJ,gFACsC,KAAK,OAAO,GAAG,GAAG;GAE5D,OAAO,KAAK,cAAc,KAAK;EACnC,CAAC,CAAC;EAGV,IAAI,KAAK,cAAc,OAAO,GAAG,KAAK;EACtC,OAAO,KAAK,cAAc,KAAK;CACnC;CAOQ,kBACJ,OAAwB;EAExB,OAAO,KAAK,cAAa,CAAE,CAAC,CAAC,KACzB,WAAW,WAA0B;GACjC,MAAM,QAAQ,OAAO;GACrB,IAAI,CAAC,OACD,OAAO,iCACG,IAAI,MAAM,6BAA6B,CAAC;GAItD,MAAM,QAAuB,IAAI,MAAM,EACnC,IAAI,MAAM,SACb,CAAA;GACD,OAAO,KACH,MAAM,YAAY,EACd,QAAQ,CAAC,YAAY,kBAAkB,EAC1C,CAAA,CAAC,CACL,CAAC,KACE,WAAW;IACP,GAAG;IACH,cACI,MAAM,gBAAgB,MAAM,oBAAoB;IACpD,KAAK,KAAK,MAAM,MAAM,UAAU,IAAG,CAAE;IACrC,KAAK,KAAK,MAAM,MAAM,UAAU,IAAG,CAAE;GACxC,EAAC,CAAC;EAEX,CAAC,CAAC;CAEV;CAGQ,cACJ,OAAwB;EAExB,OAAO,KAAK,cAAa,CAAE,CAAC,CAAC,KACzB,WACK,WACG,IAAI,YAA+B,QAAO;GACtC,IAAI,OAAO,cACP,SAAS,cAAc,KAAK,CAAC,CAChC,CAAC,WACE;IACI,SAAS,MAAM;IACf,QAAQ,CAAC,YAAY,mBAAmB;GAC3C,IACA,OAAwB,UAAiB;IACtC,IAAI,UAAU,aAAa,MAAM,CAAC,OAAO;KACrC,IAAI,MAAM,IAAI,MAAM,KAAK,CAAC;KAC1B;IACJ;IACA,MAAM,QAAQ,MAAM,UAAU;IAC9B,IAAI,KAAK;KACL,GAAG;KACH,cACI,MAAM,gBACN,MAAM,qBACN;KACJ,KAAK,KAAK,MAAM,OAAO,IAAG,CAAE;KAC5B,KAAK,KAAK,MAAM,OAAO,IAAG,CAAE;IAC/B,CAAA;IACD,IAAI,SAAQ;GAChB,CAAC;EAET,CAAC,CAAC,GAEV,YAAY,QAAgB;GACxB,QAAQ,KACJ,wDACI,KAAK,OAAO,GAAG,CAAC;GAExB,OAAO,GAAG,KAAK;EACnB,CAAC,CAAC;CAEV;CASQ,WACJ,SACA,UAA8B;EAE9B,MAAM,WAA2C,SAAS;EAC1D,IAAI,CAAC,UACD,OAAO,iCACG,IAAI,MAAM,2CAA2C,CAAC;EAIpE,MAAM,OAA6B,SAAS,MAAM,CAAC;EACnD,IAAI,KAAK,OAAO,IAAI,QAAQ,GAAG,OAAO,KAAK,WAAW,SAAS,IAAI;EAOnE,QAJI,aAAa,WACP,KAAK,SAAS,OAAO,IACrB,KAAK,YAAY,OAAO,EAE3B,CAAU,KACb,KAAK,WAA+B;GAChC,IAAI,OAAO,UAAU,GACjB,KAAK,iBAAiB,KAAK,IAAI;EAEvC,CAAC,GACD,YAAY,QAAgB;GACxB,KAAK,OAAO,IAAI,QAAQ;GACxB,QAAQ,KACJ,6BAA6B,SAAQ,+CACL,KAAK,OAAO,GAAG,GAAG;GAEtD,OAAO,KAAK,WAAW,SAAS,IAAI;EACxC,CAAC,CAAC;CAEV;CAOQ,YAAY,SAAe;EAC/B,MAAM,UAAU,mBAAmB,OAAO;EAC1C,MAAM,OAAe,KAAK,QAAQ,gBAAgB;EAClD,OAAO,KAAK,KACP,IAAc,GAAG,KAAI,KAAM,QAAO,eAAgB,CAAC,CACnD,KACG,KAAK,QACD,IAAI,KAAK,UAAe;GACpB,cAAc,KAAK;GACnB,KAAK,KAAK;GACV,KAAK,KAAK;GACV,UAAU,KAAK;EAClB,EAAC,CAAC,CACN;CAEb;CASQ,SAAS,SAAe;EAC5B,IAAI,KAAK,kBAAkB,OAAO,KAAK,YAAY,OAAO;EAE1D,OAAO,KAAK,aAAa,OAAO,CAAC,CAAC,KAC9B,YAAY,QAAgB;GACxB,KAAK,mBAAmB;GACxB,QAAQ,KACJ,2EACuB,KAAK,OAAO,GAAG,GAAG;GAE7C,OAAO,KAAK,YAAY,OAAO;EACnC,CAAC,CAAC;CAEV;CAGQ,YAAY,SAAe;EAC/B,IAAI,KAAK,cAAc,OAAO,KAAK,WAAW,OAAO;EAErD,OAAO,KAAK,SAAS,OAAO,CAAC,CAAC,KAC1B,YAAY,QAAgB;GACxB,KAAK,eAAe;GACpB,QAAQ,KACJ,0EACqB,KAAK,OAAO,GAAG,GAAG;GAE3C,OAAO,KAAK,WAAW,OAAO;EAClC,CAAC,CAAC;CAEV;CAaQ,aAAa,SAAe;EAChC,MAAM,QAA4B,KAAK,QAAQ;EAC/C,MAAM,UAAkC,KAAK,QAAO;EAEpD,OAAO,KAAK,cAAa,CAAE,CAAC,CAAC,KACzB,WAAW,WAA0B;GACjC,MAAM,QAAQ,OAAO;GACrB,IAAI,CAAC,OACD,OAAO,iCAEC,IAAI,MACA,8CAA8C,CACjD;GAIb,OAAO,KACH,MAAM,6BAA6B;IAC/B,OAAO;IACP,GAAI,QACE;KAAE,qBAAqB,CAAC,KAAK;KAAG,QAAQ;IAAK,IAC7C,CAAA;IACN,GAAI,UAAU,EAAE,cAAc,QAAO,IAAK,CAAA;GAC7C,CAAA,CAAC,CACL,CAAC,KACE,KAAK,cACA,UAAU,eAAe,CAAA,EAAA,CACrB,KAAK,MAAuB,EAAE,eAAe,CAAC,CAC9C,QACI,MAAkC,CAAC,CAAC,GAAG,OAAO,CAClD,CACA,KAAK,OAAO;IACT,UAAU,EAAE;IACZ,cAAc,EAAE,MAAM,SAAQ,KAAM;GACvC,EAAC,CAAC,CACV;EAET,CAAC,CAAC;CAEV;CAGQ,SAAS,SAAe;EAC5B,MAAM,QAA4B,KAAK,QAAQ;EAC/C,MAAM,UAAkC,KAAK,QAAO;EAEpD,OAAO,KAAK,cAAa,CAAE,CAAC,CAAC,KACzB,WACK,WACG,IAAI,YAAiC,QAAO;GACxC,IAAI,OAAO,oBAAmB,CAAE,CAAC,oBAC7B;IACI,OAAO;IACP,GAAI,QACE,EACI,uBAAuB,EACnB,SAAS,MACZ,EACJ,IACD,CAAA;IACN,GAAI,UAAU,EAAE,cAAc,QAAO,IAAK,CAAA;GAC7C,IACA,UAAgC,UAAiB;IAC9C,IAAI,UAAU,aAAa,SAAS;KAChC,IAAI,KAAK,CAAA,CAAE;KACX,IAAI,SAAQ;KACZ;IACJ;IACA,IAAI,UAAU,aAAa,IAAI;KAC3B,IAAI,MAAM,IAAI,MAAM,KAAK,CAAC;KAC1B;IACJ;IACA,IAAI,MACC,YAAY,CAAA,EAAA,CACR,QACI,MAAmB,CAAC,CAAC,EAAE,QAAQ,CACnC,CACA,KAAK,OAAoB;KACtB,UAAU,EAAE;KACZ,cAAc,EAAE,eAAe;IAClC,EAAC,CAAC;IAEX,IAAI,SAAQ;GAChB,CAAC;EAET,CAAC,CAAC,CACT;CAET;CAQQ,WAAW,SAAe;EAC9B,MAAM,QAA4B,KAAK,QAAQ;EAC/C,MAAM,WAAoC,KAAK,SAAQ;EAEvD,OAAO,KAAK,gBAAe,CAAE,CAAC,CAAC,KAC3B,WACK,aACG,IAAI,YAAiC,QAAO;GACxC,SAAS,QACL;IACI;IACA,GAAI,QACE;KACI,uBAAuB,EACnB,SAAS,MACZ;KACD,QAAQ;IACX,IACD,CAAA;IACN,GAAI,WAAW,EAAE,QAAQ,SAAQ,IAAK,CAAA;GACzC,IAEG,WACA,UACA;IACA,IAAI,UAAU,aAAa,SAAS;KAChC,IAAI,KAAK,CAAA,CAAE;KACX,IAAI,SAAQ;KACZ;IACJ;IACA,IAAI,UAAU,aAAa,IAAI;KAC3B,IAAI,MAAM,IAAI,MAAM,KAAK,CAAC;KAC1B;IACJ;IACA,IAAI,MACC,aAAa,CAAA,EAAA,CAAI,KACb,OAA0B;KACvB,UAAU,EAAE;KACZ,cACI,EAAE,qBAAqB;KAC3B,KAAK,KAAK,MACN,EAAE,UAAU,UAAU,IAAG,CAAE;KAE/B,KAAK,KAAK,MACN,EAAE,UAAU,UAAU,IAAG,CAAE;IAElC,EAAC,CACL;IAEL,IAAI,SAAQ;GAChB,CAAC;EAET,CAAC,CAAC,CACT;CAET;CAGQ,UAAO;EACX,MAAM,OAAqC,KAAK,QAAQ;EACxD,OAAO,OACD;GACI,QAAQ;IAAE,KAAK,KAAK;IAAK,KAAK,KAAK;GAAG;GACtC,QAAQ,KAAK;EAChB,IACD;CACV;CAQQ,WAAQ;EACZ,MAAM,OAAqC,KAAK,QAAQ;EACxD,IAAI,CAAC,MAAM,OAAO;EAElB,MAAM,OAAe,KAAK,UAAU;EACpC,MAAM,OACF,OAAO,KAAK,IAAI,KAAK,IAAK,KAAK,MAAM,KAAK,KAAM,GAAG,GAAG,GAAI;EAC9D,OAAO;GACH,OAAO,KAAK,MAAM;GAClB,OAAO,KAAK,MAAM;GAClB,MAAM,KAAK,MAAM;GACjB,MAAM,KAAK,MAAM;EACpB;CACL;CAGQ,WAAQ;EACZ,MAAM,aAAmC,KAAK,QAAQ,WAAW,CAAA;EACjE,OAAO,WAAW,SAAS,aAAa;CAC5C;CASQ,OAAO,KAAY;EACvB,IAAI,eAAe,SAAS,IAAI,SAAS,OAAO,IAAI;EAEpD,MAAM,YACD,KAA6B,OAG/B;EACH,IAAI,CAAC,WAAW,OAAO;EAEvB,OAAO,CAAC,UAAU,QAAQ,UAAU,OAAO,CAAC,CACvC,QAAQ,UAA8B,CAAC,CAAC,KAAK,CAAC,CAC9C,KAAK,KAAK;CACnB;CASQ,MAAM,QAAiC;EAC3C,OAAO,WAAW,QAAQ,WAAW,SAC/B,SACA,OAAO,MAAM;CACvB;CA9eS;EAAA,KAAA,OAAA,GAAA,mBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAAmB,MAAA,CAAA;GAAA,QAAA,GAAA,gBAAA;EAAA,CAAA;CAAA;CAAnB;EAAA,KAAA,QAAA,GAAA,sBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAAmB,YAFhB;EAAM,CAAA;CAAA;;AAET,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAmB,YAAA,CAAA;EAH/B,MAAA;EAAW,MAAA,CAAA,EACR,YAAY,OACf,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geosdi/ngx-geocoding",
3
- "version": "1.2.0",
3
+ "version": "2.0.0",
4
4
  "description": "Component to get a list of place with a geocoding service",
5
5
  "author": "Salvia Vito (vito.salvia@gmail.com)",
6
6
  "keywords": [
@@ -12,9 +12,8 @@
12
12
  ],
13
13
  "license": "MIT",
14
14
  "peerDependencies": {
15
- "@angular/common": ">=20.0.0",
16
- "@angular/core": ">=20.0.0",
17
- "typescript": ">=5.0.0",
15
+ "@angular/common": ">=22.0.0",
16
+ "@angular/core": ">=22.0.0",
18
17
  "rxjs": ">=7.8.0"
19
18
  },
20
19
  "sideEffects": false,