{"version":3,"file":"resilient-http-client.mjs","sources":["../../../projects/resilient-http-client/src/lib/util/rx/resilience.rx-operator.ts","../../../projects/resilient-http-client/src/lib/util/rx/resilience.rx-operator.config.ts","../../../projects/resilient-http-client/src/lib/service/resilient-http-client.service.ts","../../../projects/resilient-http-client/src/public-api.ts","../../../projects/resilient-http-client/src/resilient-http-client.ts"],"sourcesContent":["import { concatMap, delay, map, MonoTypeOperatorFunction, of, retry, Subject, take, tap } from 'rxjs';\nimport { IResilienceConfig, TTopicPropName } from '../../model/type/resilience.rx-operator.type';\n\nexport const getTopicSpecificBooleanOrDefault = (config: IResilienceConfig, propertyName: TTopicPropName): boolean => {\n    const topicConfig = config.topicToConfigDict[config.topic];\n    const isDefinedByTopicConfig = topicConfig && topicConfig[propertyName] !== undefined;\n\n    return isDefinedByTopicConfig ? (topicConfig[propertyName] as boolean) : config[propertyName];\n};\n\nconst isRetryDisabled = (config: IResilienceConfig): boolean =>\n    getTopicSpecificBooleanOrDefault(config, 'disableRetry');\n\nconst waitForUserDecision = (config: IResilienceConfig): boolean =>\n    getTopicSpecificBooleanOrDefault(config, 'waitForUserDecision');\n\nexport const shouldLogResult = (config: IResilienceConfig): boolean =>\n    getTopicSpecificBooleanOrDefault(config, 'logResult');\n\nexport const shouldTrace = (config: IResilienceConfig): boolean => getTopicSpecificBooleanOrDefault(config, 'trace');\n\nexport const applyResilience = <T>(config: IResilienceConfig, uuid: string): MonoTypeOperatorFunction<T> => {\n    const userRetryOrCancelSubject = new Subject<boolean>();\n    let retryCount = 0;\n\n    return retry<T>({\n        delay: (error) =>\n            of(error).pipe(\n                concatMap((err) => {\n                    if (isRetryDisabled(config) || !config.retryOnStatusCodeList.includes(err.status)) {\n                        const topicSpecificMessageOrEmpty = config.topicToConfigDict[config.topic]?.failMessage || '';\n\n                        config.onFail(config.topic, uuid, topicSpecificMessageOrEmpty);\n                        throw err;\n                    }\n                    retryCount = retryCount + 1;\n                    const retries = retryCount;\n\n                    if (retryCount <= config.retryIntervalInMillisList.length) {\n                        return of(err).pipe(\n                            tap(() =>\n                                config.onRequestRetry(\n                                    config.topic,\n                                    uuid,\n                                    retries,\n                                    config.retryIntervalInMillisList[retries - 1],\n                                    err.status,\n                                ),\n                            ),\n                            delay(config.retryIntervalInMillisList[retryCount - 1]),\n                        );\n                    } else {\n                        retryCount = 0;\n\n                        if (waitForUserDecision(config)) {\n                            config.onWaitingForUserDecision(\n                                config.topic,\n                                uuid,\n                                retries,\n                                err.status,\n                                userRetryOrCancelSubject,\n                            );\n                            return userRetryOrCancelSubject.asObservable().pipe(\n                                take(1),\n                                map((shouldRetry) => {\n                                    if (shouldRetry) {\n                                        config.onRequestRetry(\n                                            config.topic,\n                                            uuid,\n                                            retries,\n                                            config.retryIntervalInMillisList[retries - 1],\n                                            err.status,\n                                        );\n                                        return of(err);\n                                    }\n                                    const topicSpecificMessageOrEmpty =\n                                        config.topicToConfigDict[config.topic]?.failMessage || '';\n\n                                    config.onFail(config.topic, uuid, topicSpecificMessageOrEmpty);\n                                    throw err;\n                                }),\n                            );\n                        } else {\n                            const topicSpecificMessageOrEmpty =\n                                config.topicToConfigDict[config.topic]?.failMessage || '';\n\n                            config.onFail(config.topic, uuid, topicSpecificMessageOrEmpty);\n                            throw err;\n                        }\n                    }\n                }),\n            ),\n    });\n};\n","import { IResilienceConfig } from '../../model/type/resilience.rx-operator.type';\nimport { HttpStatusCode } from '@angular/common/http';\n\nexport const DEFAULT_RESILIENCE_CONFIG: Partial<IResilienceConfig> = {\n    isDelayedAfterMs: 3000,\n    disableRetry: false,\n    logResult: false,\n    trace: false,\n    waitForUserDecision: false,\n    retryOnStatusCodeList: [\n        HttpStatusCode.RequestTimeout,\n        HttpStatusCode.TooManyRequests,\n        HttpStatusCode.InternalServerError,\n        HttpStatusCode.BadGateway,\n        HttpStatusCode.ServiceUnavailable,\n        HttpStatusCode.GatewayTimeout,\n    ],\n    retryIntervalInMillisList: [0, 200, 500, 1000, 1000],\n    topicToConfigDict: {},\n    onWaitingForUserDecision: (): void => {},\n    onFail: (): void => {},\n    onRequestDelayed: (): void => {},\n    onRequestRetry: (): void => {},\n    onRequestStart: (): void => {},\n    onRequestFinalize: (): void => {},\n};\n","import { HttpClient, HttpResponse } from '@angular/common/http';\nimport { Injectable } from '@angular/core';\nimport { catchError, finalize, map, Observable, of, take, tap, throwError, timer } from 'rxjs';\nimport { applyResilience, shouldLogResult, shouldTrace } from '../util/rx/resilience.rx-operator';\nimport { v4 as uuidv4 } from 'uuid';\nimport { THttpGetOption } from '../model/type/http-get-options.type';\nimport { IResilienceConfig } from '../model/type/resilience.rx-operator.type';\nimport { DEFAULT_RESILIENCE_CONFIG } from '../util/rx/resilience.rx-operator.config';\n\n@Injectable({\n    providedIn: 'root',\n})\nexport class ResilientHttpClientService {\n    constructor(private readonly httpClient: HttpClient) {}\n\n    public get<T>(url: string, resilienceConfig: Partial<IResilienceConfig>, options?: THttpGetOption): Observable<T> {\n        const finalConfig = {\n            ...DEFAULT_RESILIENCE_CONFIG,\n            ...resilienceConfig,\n        } as IResilienceConfig;\n        const uuid = uuidv4();\n        const isDelayedSubscription = timer(finalConfig.isDelayedAfterMs)\n            .pipe(take(1))\n            .subscribe(() => {\n                finalConfig.onRequestDelayed(finalConfig.topic, uuid);\n            });\n        const timeStart = Date.now();\n\n        finalConfig.onRequestStart(finalConfig.topic, uuid);\n\n        return this.httpClient\n            .get<T>(url, {\n                ...options,\n                observe: 'response',\n            })\n            .pipe(\n                applyResilience(finalConfig, uuid),\n                map((res: HttpResponse<T>) => res.body as T),\n                tap((res) => {\n                    if (shouldLogResult(finalConfig)) {\n                        // eslint-disable-next-line no-console\n                        console.log(finalConfig.topic, res);\n                    }\n                }),\n                catchError((err) => {\n                    const topicRelatedConfig = finalConfig.topicToConfigDict[finalConfig.topic];\n\n                    if (topicRelatedConfig) {\n                        if (topicRelatedConfig.failoverResponse) {\n                            return of(topicRelatedConfig.failoverResponse as T);\n                        }\n                    }\n                    return throwError(() => err);\n                }),\n                finalize(() => {\n                    if (shouldTrace(finalConfig)) {\n                        const timeEnd = Date.now();\n                        // eslint-disable-next-line no-console\n                        console.log(\n                            `Fetch time in ms of call-topic ${finalConfig.topic}:`,\n                            finalConfig.topic,\n                            uuid,\n                            timeEnd - timeStart,\n                        );\n                    }\n                    finalConfig.onRequestFinalize(finalConfig.topic, uuid);\n                    isDelayedSubscription.unsubscribe();\n                }),\n            );\n    }\n}\n","/*\n * Public API Surface of resilient-http-client\n */\n\nexport * from './lib/model/type/resilience.rx-operator.type';\nexport * from './lib/model/type/http-get-options.type';\nexport * from './lib/util/rx/resilience.rx-operator';\nexport * from './lib/util/rx/resilience.rx-operator.config';\nexport * from './lib/service/resilient-http-client.service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["uuidv4"],"mappings":";;;;;;;MAGa,gCAAgC,GAAG,CAAC,MAAyB,EAAE,YAA4B,KAAa;IACjH,MAAM,WAAW,GAAG,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,KAAK,CAAC;IAC1D,MAAM,sBAAsB,GAAG,WAAW,IAAI,WAAW,CAAC,YAAY,CAAC,KAAK,SAAS;AAErF,IAAA,OAAO,sBAAsB,GAAI,WAAW,CAAC,YAAY,CAAa,GAAG,MAAM,CAAC,YAAY,CAAC;AACjG;AAEA,MAAM,eAAe,GAAG,CAAC,MAAyB,KAC9C,gCAAgC,CAAC,MAAM,EAAE,cAAc,CAAC;AAE5D,MAAM,mBAAmB,GAAG,CAAC,MAAyB,KAClD,gCAAgC,CAAC,MAAM,EAAE,qBAAqB,CAAC;AAE5D,MAAM,eAAe,GAAG,CAAC,MAAyB,KACrD,gCAAgC,CAAC,MAAM,EAAE,WAAW;AAEjD,MAAM,WAAW,GAAG,CAAC,MAAyB,KAAc,gCAAgC,CAAC,MAAM,EAAE,OAAO;MAEtG,eAAe,GAAG,CAAI,MAAyB,EAAE,IAAY,KAAiC;AACvG,IAAA,MAAM,wBAAwB,GAAG,IAAI,OAAO,EAAW;IACvD,IAAI,UAAU,GAAG,CAAC;AAElB,IAAA,OAAO,KAAK,CAAI;AACZ,QAAA,KAAK,EAAE,CAAC,KAAK,KACT,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CACV,SAAS,CAAC,CAAC,GAAG,KAAI;AACd,YAAA,IAAI,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;AAC/E,gBAAA,MAAM,2BAA2B,GAAG,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,WAAW,IAAI,EAAE;gBAE7F,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,2BAA2B,CAAC;AAC9D,gBAAA,MAAM,GAAG;;AAEb,YAAA,UAAU,GAAG,UAAU,GAAG,CAAC;YAC3B,MAAM,OAAO,GAAG,UAAU;YAE1B,IAAI,UAAU,IAAI,MAAM,CAAC,yBAAyB,CAAC,MAAM,EAAE;gBACvD,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CACf,GAAG,CAAC,MACA,MAAM,CAAC,cAAc,CACjB,MAAM,CAAC,KAAK,EACZ,IAAI,EACJ,OAAO,EACP,MAAM,CAAC,yBAAyB,CAAC,OAAO,GAAG,CAAC,CAAC,EAC7C,GAAG,CAAC,MAAM,CACb,CACJ,EACD,KAAK,CAAC,MAAM,CAAC,yBAAyB,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAC1D;;iBACE;gBACH,UAAU,GAAG,CAAC;AAEd,gBAAA,IAAI,mBAAmB,CAAC,MAAM,CAAC,EAAE;AAC7B,oBAAA,MAAM,CAAC,wBAAwB,CAC3B,MAAM,CAAC,KAAK,EACZ,IAAI,EACJ,OAAO,EACP,GAAG,CAAC,MAAM,EACV,wBAAwB,CAC3B;AACD,oBAAA,OAAO,wBAAwB,CAAC,YAAY,EAAE,CAAC,IAAI,CAC/C,IAAI,CAAC,CAAC,CAAC,EACP,GAAG,CAAC,CAAC,WAAW,KAAI;wBAChB,IAAI,WAAW,EAAE;4BACb,MAAM,CAAC,cAAc,CACjB,MAAM,CAAC,KAAK,EACZ,IAAI,EACJ,OAAO,EACP,MAAM,CAAC,yBAAyB,CAAC,OAAO,GAAG,CAAC,CAAC,EAC7C,GAAG,CAAC,MAAM,CACb;AACD,4BAAA,OAAO,EAAE,CAAC,GAAG,CAAC;;AAElB,wBAAA,MAAM,2BAA2B,GAC7B,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,WAAW,IAAI,EAAE;wBAE7D,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,2BAA2B,CAAC;AAC9D,wBAAA,MAAM,GAAG;qBACZ,CAAC,CACL;;qBACE;AACH,oBAAA,MAAM,2BAA2B,GAC7B,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,WAAW,IAAI,EAAE;oBAE7D,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,2BAA2B,CAAC;AAC9D,oBAAA,MAAM,GAAG;;;AAGrB,SAAC,CAAC,CACL;AACR,KAAA,CAAC;AACN;;AC1Fa,MAAA,yBAAyB,GAA+B;AACjE,IAAA,gBAAgB,EAAE,IAAI;AACtB,IAAA,YAAY,EAAE,KAAK;AACnB,IAAA,SAAS,EAAE,KAAK;AAChB,IAAA,KAAK,EAAE,KAAK;AACZ,IAAA,mBAAmB,EAAE,KAAK;AAC1B,IAAA,qBAAqB,EAAE;AACnB,QAAA,cAAc,CAAC,cAAc;AAC7B,QAAA,cAAc,CAAC,eAAe;AAC9B,QAAA,cAAc,CAAC,mBAAmB;AAClC,QAAA,cAAc,CAAC,UAAU;AACzB,QAAA,cAAc,CAAC,kBAAkB;AACjC,QAAA,cAAc,CAAC,cAAc;AAChC,KAAA;IACD,yBAAyB,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC;AACpD,IAAA,iBAAiB,EAAE,EAAE;AACrB,IAAA,wBAAwB,EAAE,MAAW,GAAG;AACxC,IAAA,MAAM,EAAE,MAAW,GAAG;AACtB,IAAA,gBAAgB,EAAE,MAAW,GAAG;AAChC,IAAA,cAAc,EAAE,MAAW,GAAG;AAC9B,IAAA,cAAc,EAAE,MAAW,GAAG;AAC9B,IAAA,iBAAiB,EAAE,MAAW,GAAG;;;MCZxB,0BAA0B,CAAA;AACnC,IAAA,WAAA,CAA6B,UAAsB,EAAA;QAAtB,IAAU,CAAA,UAAA,GAAV,UAAU;;AAEhC,IAAA,GAAG,CAAI,GAAW,EAAE,gBAA4C,EAAE,OAAwB,EAAA;AAC7F,QAAA,MAAM,WAAW,GAAG;AAChB,YAAA,GAAG,yBAAyB;AAC5B,YAAA,GAAG,gBAAgB;SACD;AACtB,QAAA,MAAM,IAAI,GAAGA,EAAM,EAAE;AACrB,QAAA,MAAM,qBAAqB,GAAG,KAAK,CAAC,WAAW,CAAC,gBAAgB;AAC3D,aAAA,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;aACZ,SAAS,CAAC,MAAK;YACZ,WAAW,CAAC,gBAAgB,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC;AACzD,SAAC,CAAC;AACN,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE;QAE5B,WAAW,CAAC,cAAc,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC;QAEnD,OAAO,IAAI,CAAC;aACP,GAAG,CAAI,GAAG,EAAE;AACT,YAAA,GAAG,OAAO;AACV,YAAA,OAAO,EAAE,UAAU;SACtB;aACA,IAAI,CACD,eAAe,CAAC,WAAW,EAAE,IAAI,CAAC,EAClC,GAAG,CAAC,CAAC,GAAoB,KAAK,GAAG,CAAC,IAAS,CAAC,EAC5C,GAAG,CAAC,CAAC,GAAG,KAAI;AACR,YAAA,IAAI,eAAe,CAAC,WAAW,CAAC,EAAE;;gBAE9B,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC;;AAE3C,SAAC,CAAC,EACF,UAAU,CAAC,CAAC,GAAG,KAAI;YACf,MAAM,kBAAkB,GAAG,WAAW,CAAC,iBAAiB,CAAC,WAAW,CAAC,KAAK,CAAC;YAE3E,IAAI,kBAAkB,EAAE;AACpB,gBAAA,IAAI,kBAAkB,CAAC,gBAAgB,EAAE;AACrC,oBAAA,OAAO,EAAE,CAAC,kBAAkB,CAAC,gBAAqB,CAAC;;;AAG3D,YAAA,OAAO,UAAU,CAAC,MAAM,GAAG,CAAC;AAChC,SAAC,CAAC,EACF,QAAQ,CAAC,MAAK;AACV,YAAA,IAAI,WAAW,CAAC,WAAW,CAAC,EAAE;AAC1B,gBAAA,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE;;AAE1B,gBAAA,OAAO,CAAC,GAAG,CACP,kCAAkC,WAAW,CAAC,KAAK,CAAG,CAAA,CAAA,EACtD,WAAW,CAAC,KAAK,EACjB,IAAI,EACJ,OAAO,GAAG,SAAS,CACtB;;YAEL,WAAW,CAAC,iBAAiB,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC;YACtD,qBAAqB,CAAC,WAAW,EAAE;SACtC,CAAC,CACL;;8GAxDA,0BAA0B,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,UAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAA1B,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,0BAA0B,cAFvB,MAAM,EAAA,CAAA,CAAA;;2FAET,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBAHtC,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACR,oBAAA,UAAU,EAAE,MAAM;AACrB,iBAAA;;;ACXD;;AAEG;;ACFH;;AAEG;;;;"}