@arsedizioni/ars-utils 22.0.54 → 22.0.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/arsedizioni-ars-utils-clipper.common.mjs +96 -102
- package/fesm2022/arsedizioni-ars-utils-clipper.common.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-evolution.common.mjs +218 -220
- package/fesm2022/arsedizioni-ars-utils-evolution.common.mjs.map +1 -1
- package/package.json +1 -1
- package/types/arsedizioni-ars-utils-clipper.common.d.ts +18 -33
- package/types/arsedizioni-ars-utils-evolution.common.d.ts +19 -28
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { signal, computed, inject, Service, DestroyRef, Injector
|
|
3
|
-
import { HttpClient, HttpHeaders, HttpRequest
|
|
2
|
+
import { signal, computed, inject, Service, DestroyRef, Injector } from '@angular/core';
|
|
3
|
+
import { HttpErrorResponse, HttpClient, HttpHeaders, HttpRequest } from '@angular/common/http';
|
|
4
4
|
import { BroadcastService, SystemUtils, SplashService } from '@arsedizioni/ars-utils/core';
|
|
5
|
-
import { throwError, of, EMPTY
|
|
6
|
-
import { catchError, map, finalize } from 'rxjs/operators';
|
|
5
|
+
import { catchError, throwError, of, EMPTY } from 'rxjs';
|
|
6
|
+
import { catchError as catchError$1, map, finalize } from 'rxjs/operators';
|
|
7
7
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
8
8
|
|
|
9
9
|
const ClipperMessages = {
|
|
@@ -2191,6 +2191,93 @@ const NotesColors = [{ name: "Verde", value: "#2E8B74" },
|
|
|
2191
2191
|
{ name: "Indaco", value: "#5B6EBF" }
|
|
2192
2192
|
];
|
|
2193
2193
|
|
|
2194
|
+
/** Minimum milliseconds between consecutive error broadcasts (debounce guard). */
|
|
2195
|
+
const ERROR_DEBOUNCE_MS = 5000;
|
|
2196
|
+
/**
|
|
2197
|
+
* Builds the Clipper auth HTTP interceptor.
|
|
2198
|
+
*
|
|
2199
|
+
* Takes its two inputs — the Clipper base URI and the service flags — directly
|
|
2200
|
+
* as arguments (captured in the closure), so it never injects ClipperService:
|
|
2201
|
+
* registering it does not pull the full Clipper service into the eager bundle.
|
|
2202
|
+
*
|
|
2203
|
+
* Register it with `withInterceptors`:
|
|
2204
|
+
* @example
|
|
2205
|
+
* provideHttpClient(withInterceptors([
|
|
2206
|
+
* clipperAuthInterceptor(environment.serviceUri, ClipperServiceFlags.NotifySystemErrors),
|
|
2207
|
+
* ]))
|
|
2208
|
+
*
|
|
2209
|
+
* @param serviceUri - Base URI of the Clipper service; only requests starting with it are handled.
|
|
2210
|
+
* @param flags - Service flags (e.g. NotifySystemErrors). Defaults to None.
|
|
2211
|
+
* @returns An `HttpInterceptorFn` ready to register.
|
|
2212
|
+
*/
|
|
2213
|
+
function clipperAuthInterceptor(serviceUri, flags = ClipperServiceFlags.None) {
|
|
2214
|
+
// Debounce state, persisted across requests via the factory closure.
|
|
2215
|
+
let lastErrorTime = -1;
|
|
2216
|
+
/**
|
|
2217
|
+
* Broadcasts a user-friendly message for a Clipper HTTP error, debounced.
|
|
2218
|
+
* @param error - The raw error value thrown by the HTTP layer.
|
|
2219
|
+
* @param broadcastService - The broadcast service for the current request.
|
|
2220
|
+
* @returns void
|
|
2221
|
+
*/
|
|
2222
|
+
function handleError(error, broadcastService) {
|
|
2223
|
+
if (!(error instanceof HttpErrorResponse))
|
|
2224
|
+
return;
|
|
2225
|
+
// Reject only errors that explicitly belong to a different service; a missing
|
|
2226
|
+
// url (network failure on a Clipper request) is allowed through.
|
|
2227
|
+
if (error.url && !error.url.startsWith(serviceUri))
|
|
2228
|
+
return;
|
|
2229
|
+
const errorStatus = error.status;
|
|
2230
|
+
const shouldNotify = errorStatus === 0 ||
|
|
2231
|
+
(errorStatus > 0 && errorStatus < 500) ||
|
|
2232
|
+
(flags & ClipperServiceFlags.NotifySystemErrors) > 0;
|
|
2233
|
+
if (!shouldNotify)
|
|
2234
|
+
return;
|
|
2235
|
+
const now = Date.now();
|
|
2236
|
+
if (now - lastErrorTime <= ERROR_DEBOUNCE_MS)
|
|
2237
|
+
return;
|
|
2238
|
+
lastErrorTime = now;
|
|
2239
|
+
let message;
|
|
2240
|
+
switch (errorStatus) {
|
|
2241
|
+
case 0:
|
|
2242
|
+
message = "In questo momento Clipper non è disponibile. Riprova tra qualche minuto.";
|
|
2243
|
+
break;
|
|
2244
|
+
case 403:
|
|
2245
|
+
message = "Non hai i permessi necessari per eseguire l'operazione richiesta.";
|
|
2246
|
+
break;
|
|
2247
|
+
default:
|
|
2248
|
+
message = (error.error?.['message'] ??
|
|
2249
|
+
error.message ??
|
|
2250
|
+
"Impossibile eseguire l'operazione richiesta.").replaceAll('\r\n', '</p><p>');
|
|
2251
|
+
break;
|
|
2252
|
+
}
|
|
2253
|
+
broadcastService.sendMessage(ClipperMessages.ERROR, {
|
|
2254
|
+
invalidateSession: errorStatus === 405 || errorStatus === 410,
|
|
2255
|
+
message,
|
|
2256
|
+
title: "Errore in Clipper",
|
|
2257
|
+
errorStatus,
|
|
2258
|
+
service: serviceUri
|
|
2259
|
+
});
|
|
2260
|
+
}
|
|
2261
|
+
// The interceptor itself. Runs in an injection context, so `inject()` works.
|
|
2262
|
+
return (request, next) => {
|
|
2263
|
+
if (!request.url.startsWith(serviceUri)) {
|
|
2264
|
+
return next(request);
|
|
2265
|
+
}
|
|
2266
|
+
const broadcastService = inject(BroadcastService);
|
|
2267
|
+
const authenticatedRequest = request.clone({
|
|
2268
|
+
withCredentials: true,
|
|
2269
|
+
setHeaders: {
|
|
2270
|
+
'ngsw-bypass': 'ngsw-bypass',
|
|
2271
|
+
'X-Client-Id': sessionStorage.getItem('clipper_client_id') ?? ''
|
|
2272
|
+
}
|
|
2273
|
+
});
|
|
2274
|
+
return next(authenticatedRequest).pipe(catchError((error) => {
|
|
2275
|
+
handleError(error, broadcastService);
|
|
2276
|
+
return throwError(() => error);
|
|
2277
|
+
}));
|
|
2278
|
+
};
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2194
2281
|
/**
|
|
2195
2282
|
* Document search, references, export and metadata, plus the dashboard counters,
|
|
2196
2283
|
* taxonomy/topics/tags lookups, the working-documents "bag" and saved searches.
|
|
@@ -2625,7 +2712,7 @@ class ClipperLoginService {
|
|
|
2625
2712
|
: new HttpHeaders()
|
|
2626
2713
|
.set("Authorization", 'Bearer ' + oauthAccessToken)
|
|
2627
2714
|
})
|
|
2628
|
-
.pipe(catchError(err => {
|
|
2715
|
+
.pipe(catchError$1(err => {
|
|
2629
2716
|
return throwError(() => err);
|
|
2630
2717
|
}), map((r) => {
|
|
2631
2718
|
if (r.success) {
|
|
@@ -2667,7 +2754,7 @@ class ClipperLoginService {
|
|
|
2667
2754
|
confirmIdentity(code) {
|
|
2668
2755
|
return this.httpClient
|
|
2669
2756
|
.post(this.core.serviceUri + '/login/confirm/' + code, {})
|
|
2670
|
-
.pipe(catchError((err) => {
|
|
2757
|
+
.pipe(catchError$1((err) => {
|
|
2671
2758
|
return throwError(() => err);
|
|
2672
2759
|
}), map((r) => {
|
|
2673
2760
|
if (r.success) {
|
|
@@ -2687,7 +2774,7 @@ class ClipperLoginService {
|
|
|
2687
2774
|
this.core.clear(true);
|
|
2688
2775
|
// Clean up
|
|
2689
2776
|
localStorage.removeItem('clipper_context');
|
|
2690
|
-
}), catchError((_e) => {
|
|
2777
|
+
}), catchError$1((_e) => {
|
|
2691
2778
|
return of([]);
|
|
2692
2779
|
}));
|
|
2693
2780
|
}
|
|
@@ -2993,7 +3080,7 @@ class ClipperCoreService {
|
|
|
2993
3080
|
*/
|
|
2994
3081
|
ping() {
|
|
2995
3082
|
this.httpClient.get(this._serviceUri + '/ping?nocache=' + SystemUtils.generateUUID())
|
|
2996
|
-
.pipe(catchError(() => { return EMPTY; }))
|
|
3083
|
+
.pipe(catchError$1(() => { return EMPTY; }))
|
|
2997
3084
|
.subscribe();
|
|
2998
3085
|
}
|
|
2999
3086
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: ClipperCoreService, deps: [], target: i0.ɵɵFactoryTarget.Service }); }
|
|
@@ -3687,99 +3774,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImpor
|
|
|
3687
3774
|
type: Service
|
|
3688
3775
|
}] });
|
|
3689
3776
|
|
|
3690
|
-
/** Minimum milliseconds between consecutive error broadcasts (debounce guard). */
|
|
3691
|
-
const ERROR_DEBOUNCE_MS = 5000;
|
|
3692
|
-
/**
|
|
3693
|
-
* HTTP interceptor that attaches Clipper authentication headers to every request
|
|
3694
|
-
* targeting the Clipper service, and broadcasts user-friendly error messages
|
|
3695
|
-
* when the server returns an error response.
|
|
3696
|
-
*/
|
|
3697
|
-
class ClipperAuthInterceptor {
|
|
3698
|
-
constructor() {
|
|
3699
|
-
this.clipperService = inject(ClipperService);
|
|
3700
|
-
this.broadcastService = inject(BroadcastService);
|
|
3701
|
-
this.lastErrorTime = -1;
|
|
3702
|
-
}
|
|
3703
|
-
/**
|
|
3704
|
-
* Intercepts every outgoing HTTP request.
|
|
3705
|
-
* When the request targets the Clipper service URI, attaches credentials and
|
|
3706
|
-
* a client-ID header, then pipes the response through an error handler.
|
|
3707
|
-
* @param request - The outgoing HTTP request.
|
|
3708
|
-
* @param next - The next handler in the interceptor chain.
|
|
3709
|
-
* @returns An observable of the HTTP event stream.
|
|
3710
|
-
*/
|
|
3711
|
-
intercept(request, next) {
|
|
3712
|
-
if (!request.url.startsWith(this.clipperService.serviceUri)) {
|
|
3713
|
-
return next.handle(request);
|
|
3714
|
-
}
|
|
3715
|
-
const authenticatedRequest = request.clone({
|
|
3716
|
-
withCredentials: true,
|
|
3717
|
-
setHeaders: {
|
|
3718
|
-
'ngsw-bypass': 'ngsw-bypass',
|
|
3719
|
-
'X-Client-Id': sessionStorage.getItem('clipper_client_id') ?? ''
|
|
3720
|
-
}
|
|
3721
|
-
});
|
|
3722
|
-
return next.handle(authenticatedRequest).pipe(catchError$1((error) => {
|
|
3723
|
-
this.handleError(error);
|
|
3724
|
-
return throwError(() => error);
|
|
3725
|
-
}));
|
|
3726
|
-
}
|
|
3727
|
-
/**
|
|
3728
|
-
* Processes an HTTP error, broadcasting a user-friendly message when appropriate.
|
|
3729
|
-
* Errors are debounced: only one message is sent per `ERROR_DEBOUNCE_MS` window.
|
|
3730
|
-
*
|
|
3731
|
-
* This handler only ever runs for requests already targeting the Clipper service
|
|
3732
|
-
* (see `intercept`). A transport-level failure produces an `HttpErrorResponse`
|
|
3733
|
-
* with status `0` and a `null` url, so the url is only validated when present —
|
|
3734
|
-
* that way genuine network failures still surface the "service unavailable" message.
|
|
3735
|
-
* @param error - The raw error value thrown by the HTTP layer.
|
|
3736
|
-
*/
|
|
3737
|
-
handleError(error) {
|
|
3738
|
-
if (!(error instanceof HttpErrorResponse))
|
|
3739
|
-
return;
|
|
3740
|
-
// Reject only errors that explicitly belong to a different service; a missing
|
|
3741
|
-
// url (network failure on a Clipper request) is allowed through.
|
|
3742
|
-
if (error.url && !error.url.startsWith(this.clipperService.serviceUri))
|
|
3743
|
-
return;
|
|
3744
|
-
const errorStatus = error.status;
|
|
3745
|
-
const shouldNotify = errorStatus === 0 ||
|
|
3746
|
-
(errorStatus > 0 && errorStatus < 500) ||
|
|
3747
|
-
(this.clipperService.flags & ClipperServiceFlags.NotifySystemErrors) > 0;
|
|
3748
|
-
if (!shouldNotify)
|
|
3749
|
-
return;
|
|
3750
|
-
const now = Date.now();
|
|
3751
|
-
if (now - this.lastErrorTime <= ERROR_DEBOUNCE_MS)
|
|
3752
|
-
return;
|
|
3753
|
-
this.lastErrorTime = now;
|
|
3754
|
-
let message;
|
|
3755
|
-
switch (errorStatus) {
|
|
3756
|
-
case 0:
|
|
3757
|
-
message = "In questo momento Clipper non è disponibile. Riprova tra qualche minuto.";
|
|
3758
|
-
break;
|
|
3759
|
-
case 403:
|
|
3760
|
-
message = "Non hai i permessi necessari per eseguire l'operazione richiesta.";
|
|
3761
|
-
break;
|
|
3762
|
-
default:
|
|
3763
|
-
message = (error.error?.['message'] ??
|
|
3764
|
-
error.message ??
|
|
3765
|
-
"Impossibile eseguire l'operazione richiesta.").replaceAll('\r\n', '</p><p>');
|
|
3766
|
-
break;
|
|
3767
|
-
}
|
|
3768
|
-
this.broadcastService.sendMessage(ClipperMessages.ERROR, {
|
|
3769
|
-
invalidateSession: errorStatus === 405 || errorStatus === 410,
|
|
3770
|
-
message,
|
|
3771
|
-
title: "Errore in Clipper",
|
|
3772
|
-
errorStatus,
|
|
3773
|
-
service: this.clipperService.serviceUri
|
|
3774
|
-
});
|
|
3775
|
-
}
|
|
3776
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: ClipperAuthInterceptor, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3777
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: ClipperAuthInterceptor }); }
|
|
3778
|
-
}
|
|
3779
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: ClipperAuthInterceptor, decorators: [{
|
|
3780
|
-
type: Injectable
|
|
3781
|
-
}] });
|
|
3782
|
-
|
|
3783
3777
|
// Public API surface for the Clipper services.
|
|
3784
3778
|
//
|
|
3785
3779
|
// `ClipperService` is the facade/barrel: inject it and reach a feature via its
|
|
@@ -3795,5 +3789,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImpor
|
|
|
3795
3789
|
* Generated bundle index. Do not edit.
|
|
3796
3790
|
*/
|
|
3797
3791
|
|
|
3798
|
-
export { ClipperAccountService, ClipperArchiveCopyMode, ClipperArchiveFileStorageType, ClipperArchiveFileStorageTypes, ClipperArchiveFileType, ClipperArchiveFileTypes, ClipperArchiveFilesSearchParams, ClipperArchiveFoldersSearchParams, ClipperArchiveService,
|
|
3792
|
+
export { ClipperAccountService, ClipperArchiveCopyMode, ClipperArchiveFileStorageType, ClipperArchiveFileStorageTypes, ClipperArchiveFileType, ClipperArchiveFileTypes, ClipperArchiveFilesSearchParams, ClipperArchiveFoldersSearchParams, ClipperArchiveService, ClipperAuthors, ClipperCalendarCopyMode, ClipperCalendarSearchParams, ClipperCalendarService, ClipperCalendarState, ClipperCalendarStates, ClipperChannel, ClipperChannelSettings, ClipperChannels, ClipperCollaborationService, ClipperCoreService, ClipperDashboard, ClipperDocumentChangeReasons, ClipperDocumentContainer, ClipperDocumentsService, ClipperExportDocumentsFormat, ClipperFacet, ClipperLoginService, ClipperMessages, ClipperModel, ClipperModels, ClipperModule, ClipperModuleGroup, ClipperModuleGroups, ClipperModules, ClipperQueryDocumentFlags, ClipperQueryReferencesMode, ClipperRecurrenceType, ClipperRecurrenceTypes, ClipperRegions, ClipperSearchCalendarSnapshotResult, ClipperSearchFacetsSnapshot, ClipperSearchParams, ClipperSearchResult, ClipperSearchUtils, ClipperSectorTypes, ClipperSectors, ClipperSelectionMode, ClipperService, ClipperServiceFlags, ClipperSort, ClipperSources, ClipperTeamInfo, ClipperTeamProduct, ClipperTeamProductPermission, ClipperUpdateChannelsStateParams, ClipperUtils, NotesColors, clipperAuthInterceptor };
|
|
3799
3793
|
//# sourceMappingURL=arsedizioni-ars-utils-clipper.common.mjs.map
|