UNPKG

ynkap-payment

Version:

Module de paiement Y-Nkap pour Angular - Intégration simple des paiements mobiles (Orange Money, MTN Mobile Money)

151 lines 18.9 kB
import { Injectable } from '@angular/core'; import { timer, throwError, switchMap, tap } from 'rxjs'; import { YnkapError, ErrorCategory } from '../../error-handling/models/error.model'; import * as i0 from "@angular/core"; export class RetryService { constructor() { this.retryStates = new Map(); this.defaultRetryOptions = { maxRetries: 3, baseDelayMs: 1000, maxDelayMs: 30000, nonRetryableErrors: [ ErrorCategory.AUTHENTICATION, ErrorCategory.AUTHORIZATION, ErrorCategory.VALIDATION ] }; } /** * Initialize retry state for a transaction */ initializeRetryState(transactionId, options) { const retryOptions = { ...this.defaultRetryOptions, ...options }; const state = { attemptNumber: 0, maxRetries: retryOptions.maxRetries, nextRetryDelayMs: retryOptions.baseDelayMs, canRetry: true, transactionId }; this.retryStates.set(transactionId, state); return state; } /** * Get retry state for a transaction */ getRetryState(transactionId) { return this.retryStates.get(transactionId) || null; } /** * Check if an error is retryable */ isRetryable(error, options) { const retryOptions = { ...this.defaultRetryOptions, ...options }; // Check if error explicitly says it's not retryable if (error.retryable === false) { return false; } // Check if error category is in non-retryable list if (retryOptions.nonRetryableErrors?.includes(error.code)) { return false; } // Network errors are usually retryable if (error.code === ErrorCategory.NETWORK) { return true; } // Server errors (5xx) are retryable if (error.httpStatus && error.httpStatus >= 500) { return true; } // Payment processing errors might be retryable if (error.code === ErrorCategory.PAYMENT_PROCESSING) { return true; } // Default to retryable if not explicitly set to false return error.retryable === undefined || error.retryable === true; } /** * Calculate next retry delay with exponential backoff */ calculateRetryDelay(attemptNumber, options) { const retryOptions = { ...this.defaultRetryOptions, ...options }; // Exponential backoff: baseDelay * 2^(attempt-1) const delay = retryOptions.baseDelayMs * Math.pow(2, attemptNumber - 1); // Add some jitter to avoid thundering herd const jitter = Math.random() * 0.1 * delay; return Math.min(delay + jitter, retryOptions.maxDelayMs); } /** * Update retry state after an attempt */ updateRetryState(transactionId, error) { const state = this.retryStates.get(transactionId); if (!state) return null; state.attemptNumber++; state.lastError = error; state.canRetry = state.attemptNumber < state.maxRetries && this.isRetryable(error); if (state.canRetry) { state.nextRetryDelayMs = this.calculateRetryDelay(state.attemptNumber); } return state; } /** * Execute retry with proper delay and state management */ executeRetry(transactionId, retryFn, options) { const state = this.getRetryState(transactionId); if (!state || !state.canRetry) { return throwError(() => state?.lastError || new YnkapError('RETRY_EXHAUSTED', 'Maximum retry attempts reached')); } const retryOptions = { ...this.defaultRetryOptions, ...options }; // Call onRetry callback if provided if (retryOptions.onRetry && state.lastError) { retryOptions.onRetry(state.lastError, state.attemptNumber + 1); } // Wait for the calculated delay, then execute retry return timer(state.nextRetryDelayMs).pipe(switchMap(() => retryFn()), tap({ error: (error) => { this.updateRetryState(transactionId, error); } })); } /** * Clear retry state for a transaction */ clearRetryState(transactionId) { this.retryStates.delete(transactionId); } /** * Get human-readable retry information */ getRetryInfo(transactionId) { const state = this.getRetryState(transactionId); if (!state) return ''; if (!state.canRetry) { return 'Nombre maximum de tentatives atteint'; } const remainingAttempts = state.maxRetries - state.attemptNumber; const nextRetrySeconds = Math.ceil(state.nextRetryDelayMs / 1000); return `${remainingAttempts} tentative(s) restante(s). Prochaine tentative dans ${nextRetrySeconds}s`; } /** * Check if automatic retry should be attempted */ shouldAutoRetry(error) { // Auto-retry only for network errors and server errors return error.code === ErrorCategory.NETWORK || (error.httpStatus !== undefined && error.httpStatus >= 500); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RetryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RetryService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RetryService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmV0cnkuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3lua2FwL3NyYy9saWIvcGF5bWVudC9yZXRyeS9yZXRyeS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFjLEtBQUssRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNyRSxPQUFPLEVBQUUsVUFBVSxFQUFnQixhQUFhLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQzs7QUFjbEcsTUFBTSxPQUFPLFlBQVk7SUFIekI7UUFJVSxnQkFBVyxHQUFHLElBQUksR0FBRyxFQUFzQixDQUFDO1FBRTVDLHdCQUFtQixHQUFpQjtZQUMxQyxVQUFVLEVBQUUsQ0FBQztZQUNiLFdBQVcsRUFBRSxJQUFJO1lBQ2pCLFVBQVUsRUFBRSxLQUFLO1lBQ2pCLGtCQUFrQixFQUFFO2dCQUNsQixhQUFhLENBQUMsY0FBYztnQkFDNUIsYUFBYSxDQUFDLGFBQWE7Z0JBQzNCLGFBQWEsQ0FBQyxVQUFVO2FBQ3pCO1NBQ0YsQ0FBQztLQWtLSDtJQWhLQzs7T0FFRztJQUNILG9CQUFvQixDQUFDLGFBQXFCLEVBQUUsT0FBK0I7UUFDekUsTUFBTSxZQUFZLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxHQUFHLE9BQU8sRUFBRSxDQUFDO1FBRWpFLE1BQU0sS0FBSyxHQUFlO1lBQ3hCLGFBQWEsRUFBRSxDQUFDO1lBQ2hCLFVBQVUsRUFBRSxZQUFZLENBQUMsVUFBVTtZQUNuQyxnQkFBZ0IsRUFBRSxZQUFZLENBQUMsV0FBVztZQUMxQyxRQUFRLEVBQUUsSUFBSTtZQUNkLGFBQWE7U0FDZCxDQUFDO1FBRUYsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLEtBQUssQ0FB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QU8sc0NBQXNDLENBQUM7U0FDL0M7UUFFRCxNQUFNLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDLGFBQWEsQ0FBQztRQUNqRSxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQyxDQUFDO1FBRWxFLE9BQU8sR0FBRyxpQkFBaUIsdURBQXVELGdCQUFnQixHQUFHLENBQUM7SUFDeEcsQ0FBQztJQUVEOztPQUVHO0lBQ0gsZUFBZSxDQUFDLEtBQWlCO1FBQy9CLHVEQUF1RDtRQUN2RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssYUFBYSxDQUFDLE9BQU87WUFDcEMsQ0FBQyxLQUFLLENBQUMsVUFBVSxLQUFLLFNBQVMsSUFBSSxLQUFLLENBQUMsVUFBVSxJQUFJLEdBQUcsQ0FBQyxDQUFDO0lBQ3JFLENBQUM7K0dBN0tVLFlBQVk7bUhBQVosWUFBWSxjQUZYLE1BQU07OzRGQUVQLFlBQVk7a0JBSHhCLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgdGltZXIsIHRocm93RXJyb3IsIHN3aXRjaE1hcCwgdGFwIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBZbmthcEVycm9yLCBSZXRyeU9wdGlvbnMsIEVycm9yQ2F0ZWdvcnkgfSBmcm9tICcuLi8uLi9lcnJvci1oYW5kbGluZy9tb2RlbHMvZXJyb3IubW9kZWwnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJldHJ5U3RhdGUge1xuICBhdHRlbXB0TnVtYmVyOiBudW1iZXI7XG4gIG1heFJldHJpZXM6IG51bWJlcjtcbiAgbmV4dFJldHJ5RGVsYXlNczogbnVtYmVyO1xuICBjYW5SZXRyeTogYm9vbGVhbjtcbiAgbGFzdEVycm9yPzogWW5rYXBFcnJvcjtcbiAgdHJhbnNhY3Rpb25JZD86IHN0cmluZztcbn1cblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgUmV0cnlTZXJ2aWNlIHtcbiAgcHJpdmF0ZSByZXRyeVN0YXRlcyA9IG5ldyBNYXA8c3RyaW5nLCBSZXRyeVN0YXRlPigpO1xuICBcbiAgcHJpdmF0ZSBkZWZhdWx0UmV0cnlPcHRpb25zOiBSZXRyeU9wdGlvbnMgPSB7XG4gICAgbWF4UmV0cmllczogMyxcbiAgICBiYXNlRGVsYXlNczogMTAwMCxcbiAgICBtYXhEZWxheU1zOiAzMDAwMCxcbiAgICBub25SZXRyeWFibGVFcnJvcnM6IFtcbiAgICAgIEVycm9yQ2F0ZWdvcnkuQVVUSEVOVElDQVRJT04sXG4gICAgICBFcnJvckNhdGVnb3J5LkFVVEhPUklaQVRJT04sXG4gICAgICBFcnJvckNhdGVnb3J5LlZBTElEQVRJT05cbiAgICBdXG4gIH07XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemUgcmV0cnkgc3RhdGUgZm9yIGEgdHJhbnNhY3Rpb25cbiAgICovXG4gIGluaXRpYWxpemVSZXRyeVN0YXRlKHRyYW5zYWN0aW9uSWQ6IHN0cmluZywgb3B0aW9ucz86IFBhcnRpYWw8UmV0cnlPcHRpb25zPik6IFJldHJ5U3RhdGUge1xuICAgIGNvbnN0IHJldHJ5T3B0aW9ucyA9IHsgLi4udGhpcy5kZWZhdWx0UmV0cnlPcHRpb25zLCAuLi5vcHRpb25zIH07XG4gICAgXG4gICAgY29uc3Qgc3RhdGU6IFJldHJ5U3RhdGUgPSB7XG4gICAgICBhdHRlbXB0TnVtYmVyOiAwLFxuICAgICAgbWF4UmV0cmllczogcmV0cnlPcHRpb25zLm1heFJldHJpZXMsXG4gICAgICBuZXh0UmV0cnlEZWxheU1zOiByZXRyeU9wdGlvbnMuYmFzZURlbGF5TXMsXG4gICAgICBjYW5SZXRyeTogdHJ1ZSxcbiAgICAgIHRyYW5zYWN0aW9uSWRcbiAgICB9O1xuICAgIFxuICAgIHRoaXMucmV0cnlTdGF0ZXMuc2V0KHRyYW5zYWN0aW9uSWQsIHN0YXRlKTtcbiAgICByZXR1cm4gc3RhdGU7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHJldHJ5IHN0YXRlIGZvciBhIHRyYW5zYWN0aW9uXG4gICAqL1xuICBnZXRSZXRyeVN0YXRlKHRyYW5zYWN0aW9uSWQ6IHN0cmluZyk6IFJldHJ5U3RhdGUgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5yZXRyeVN0YXRlcy5nZXQodHJhbnNhY3Rpb25JZCkgfHwgbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBhbiBlcnJvciBpcyByZXRyeWFibGVcbiAgICovXG4gIGlzUmV0cnlhYmxlKGVycm9yOiBZbmthcEVycm9yLCBvcHRpb25zPzogUGFydGlhbDxSZXRyeU9wdGlvbnM+KTogYm9vbGVhbiB7XG4gICAgY29uc3QgcmV0cnlPcHRpb25zID0geyAuLi50aGlzLmRlZmF1bHRSZXRyeU9wdGlvbnMsIC4uLm9wdGlvbnMgfTtcblxuICAgIC8vIENoZWNrIGlmIGVycm9yIGV4cGxpY2l0bHkgc2F5cyBpdCdzIG5vdCByZXRyeWFibGVcbiAgICBpZiAoZXJyb3IucmV0cnlhYmxlID09PSBmYWxzZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIENoZWNrIGlmIGVycm9yIGNhdGVnb3J5IGlzIGluIG5vbi1yZXRyeWFibGUgbGlzdFxuICAgIGlmIChyZXRyeU9wdGlvbnMubm9uUmV0cnlhYmxlRXJyb3JzPy5pbmNsdWRlcyhlcnJvci5jb2RlIGFzIEVycm9yQ2F0ZWdvcnkpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gTmV0d29yayBlcnJvcnMgYXJlIHVzdWFsbHkgcmV0cnlhYmxlXG4gICAgaWYgKGVycm9yLmNvZGUgPT09IEVycm9yQ2F0ZWdvcnkuTkVUV09SSykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLy8gU2VydmVyIGVycm9ycyAoNXh4KSBhcmUgcmV0cnlhYmxlXG4gICAgaWYgKGVycm9yLmh0dHBTdGF0dXMgJiYgZXJyb3IuaHR0cFN0YXR1cyA+PSA1MDApIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8vIFBheW1lbnQgcHJvY2Vzc2luZyBlcnJvcnMgbWlnaHQgYmUgcmV0cnlhYmxlXG4gICAgaWYgKGVycm9yLmNvZGUgPT09IEVycm9yQ2F0ZWdvcnkuUEFZTUVOVF9QUk9DRVNTSU5HKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBEZWZhdWx0IHRvIHJldHJ5YWJsZSBpZiBub3QgZXhwbGljaXRseSBzZXQgdG8gZmFsc2VcbiAgICByZXR1cm4gZXJyb3IucmV0cnlhYmxlID09PSB1bmRlZmluZWQgfHwgZXJyb3IucmV0cnlhYmxlID09PSB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZSBuZXh0IHJldHJ5IGRlbGF5IHdpdGggZXhwb25lbnRpYWwgYmFja29mZlxuICAgKi9cbiAgY2FsY3VsYXRlUmV0cnlEZWxheShhdHRlbXB0TnVtYmVyOiBudW1iZXIsIG9wdGlvbnM/OiBQYXJ0aWFsPFJldHJ5T3B0aW9ucz4pOiBudW1iZXIge1xuICAgIGNvbnN0IHJldHJ5T3B0aW9ucyA9IHsgLi4udGhpcy5kZWZhdWx0UmV0cnlPcHRpb25zLCAuLi5vcHRpb25zIH07XG4gICAgXG4gICAgLy8gRXhwb25lbnRpYWwgYmFja29mZjogYmFzZURlbGF5ICogMl4oYXR0ZW1wdC0xKVxuICAgIGNvbnN0IGRlbGF5ID0gcmV0cnlPcHRpb25zLmJhc2VEZWxheU1zICogTWF0aC5wb3coMiwgYXR0ZW1wdE51bWJlciAtIDEpO1xuICAgIFxuICAgIC8vIEFkZCBzb21lIGppdHRlciB0byBhdm9pZCB0aHVuZGVyaW5nIGhlcmRcbiAgICBjb25zdCBqaXR0ZXIgPSBNYXRoLnJhbmRvbSgpICogMC4xICogZGVsYXk7XG4gICAgXG4gICAgcmV0dXJuIE1hdGgubWluKGRlbGF5ICsgaml0dGVyLCByZXRyeU9wdGlvbnMubWF4RGVsYXlNcyk7XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlIHJldHJ5IHN0YXRlIGFmdGVyIGFuIGF0dGVtcHRcbiAgICovXG4gIHVwZGF0ZVJldHJ5U3RhdGUodHJhbnNhY3Rpb25JZDogc3RyaW5nLCBlcnJvcjogWW5rYXBFcnJvcik6IFJldHJ5U3RhdGUgfCBudWxsIHtcbiAgICBjb25zdCBzdGF0ZSA9IHRoaXMucmV0cnlTdGF0ZXMuZ2V0KHRyYW5zYWN0aW9uSWQpO1xuICAgIGlmICghc3RhdGUpIHJldHVybiBudWxsO1xuICAgIFxuICAgIHN0YXRlLmF0dGVtcHROdW1iZXIrKztcbiAgICBzdGF0ZS5sYXN0RXJyb3IgPSBlcnJvcjtcbiAgICBzdGF0ZS5jYW5SZXRyeSA9IHN0YXRlLmF0dGVtcHROdW1iZXIgPCBzdGF0ZS5tYXhSZXRyaWVzICYmIHRoaXMuaXNSZXRyeWFibGUoZXJyb3IpO1xuICAgIFxuICAgIGlmIChzdGF0ZS5jYW5SZXRyeSkge1xuICAgICAgc3RhdGUubmV4dFJldHJ5RGVsYXlNcyA9IHRoaXMuY2FsY3VsYXRlUmV0cnlEZWxheShzdGF0ZS5hdHRlbXB0TnVtYmVyKTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIHN0YXRlO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4ZWN1dGUgcmV0cnkgd2l0aCBwcm9wZXIgZGVsYXkgYW5kIHN0YXRlIG1hbmFnZW1lbnRcbiAgICovXG4gIGV4ZWN1dGVSZXRyeTxUPihcbiAgICB0cmFuc2FjdGlvbklkOiBzdHJpbmcsIFxuICAgIHJldHJ5Rm46ICgpID0+IE9ic2VydmFibGU8VD4sXG4gICAgb3B0aW9ucz86IFBhcnRpYWw8UmV0cnlPcHRpb25zPlxuICApOiBPYnNlcnZhYmxlPFQ+IHtcbiAgICBjb25zdCBzdGF0ZSA9IHRoaXMuZ2V0UmV0cnlTdGF0ZSh0cmFuc2FjdGlvbklkKTtcbiAgICBcbiAgICBpZiAoIXN0YXRlIHx8ICFzdGF0ZS5jYW5SZXRyeSkge1xuICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gc3RhdGU/Lmxhc3RFcnJvciB8fCBuZXcgWW5rYXBFcnJvcihcbiAgICAgICAgJ1JFVFJZX0VYSEFVU1RFRCcsXG4gICAgICAgICdNYXhpbXVtIHJldHJ5IGF0dGVtcHRzIHJlYWNoZWQnXG4gICAgICApKTtcbiAgICB9XG4gICAgXG4gICAgY29uc3QgcmV0cnlPcHRpb25zID0geyAuLi50aGlzLmRlZmF1bHRSZXRyeU9wdGlvbnMsIC4uLm9wdGlvbnMgfTtcbiAgICBcbiAgICAvLyBDYWxsIG9uUmV0cnkgY2FsbGJhY2sgaWYgcHJvdmlkZWRcbiAgICBpZiAocmV0cnlPcHRpb25zLm9uUmV0cnkgJiYgc3RhdGUubGFzdEVycm9yKSB7XG4gICAgICByZXRyeU9wdGlvbnMub25SZXRyeShzdGF0ZS5sYXN0RXJyb3IsIHN0YXRlLmF0dGVtcHROdW1iZXIgKyAxKTtcbiAgICB9XG4gICAgXG4gICAgLy8gV2FpdCBmb3IgdGhlIGNhbGN1bGF0ZWQgZGVsYXksIHRoZW4gZXhlY3V0ZSByZXRyeVxuICAgIHJldHVybiB0aW1lcihzdGF0ZS5uZXh0UmV0cnlEZWxheU1zKS5waXBlKFxuICAgICAgc3dpdGNoTWFwKCgpID0+IHJldHJ5Rm4oKSksXG4gICAgICB0YXAoe1xuICAgICAgICBlcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAgICAgdGhpcy51cGRhdGVSZXRyeVN0YXRlKHRyYW5zYWN0aW9uSWQsIGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIENsZWFyIHJldHJ5IHN0YXRlIGZvciBhIHRyYW5zYWN0aW9uXG4gICAqL1xuICBjbGVhclJldHJ5U3RhdGUodHJhbnNhY3Rpb25JZDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5yZXRyeVN0YXRlcy5kZWxldGUodHJhbnNhY3Rpb25JZCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGh1bWFuLXJlYWRhYmxlIHJldHJ5IGluZm9ybWF0aW9uXG4gICAqL1xuICBnZXRSZXRyeUluZm8odHJhbnNhY3Rpb25JZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBzdGF0ZSA9IHRoaXMuZ2V0UmV0cnlTdGF0ZSh0cmFuc2FjdGlvbklkKTtcbiAgICBpZiAoIXN0YXRlKSByZXR1cm4gJyc7XG4gICAgXG4gICAgaWYgKCFzdGF0ZS5jYW5SZXRyeSkge1xuICAgICAgcmV0dXJuICdOb21icmUgbWF4aW11bSBkZSB0ZW50YXRpdmVzIGF0dGVpbnQnO1xuICAgIH1cbiAgICBcbiAgICBjb25zdCByZW1haW5pbmdBdHRlbXB0cyA9IHN0YXRlLm1heFJldHJpZXMgLSBzdGF0ZS5hdHRlbXB0TnVtYmVyO1xuICAgIGNvbnN0IG5leHRSZXRyeVNlY29uZHMgPSBNYXRoLmNlaWwoc3RhdGUubmV4dFJldHJ5RGVsYXlNcyAvIDEwMDApO1xuICAgIFxuICAgIHJldHVybiBgJHtyZW1haW5pbmdBdHRlbXB0c30gdGVudGF0aXZlKHMpIHJlc3RhbnRlKHMpLiBQcm9jaGFpbmUgdGVudGF0aXZlIGRhbnMgJHtuZXh0UmV0cnlTZWNvbmRzfXNgO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGF1dG9tYXRpYyByZXRyeSBzaG91bGQgYmUgYXR0ZW1wdGVkXG4gICAqL1xuICBzaG91bGRBdXRvUmV0cnkoZXJyb3I6IFlua2FwRXJyb3IpOiBib29sZWFuIHtcbiAgICAvLyBBdXRvLXJldHJ5IG9ubHkgZm9yIG5ldHdvcmsgZXJyb3JzIGFuZCBzZXJ2ZXIgZXJyb3JzXG4gICAgcmV0dXJuIGVycm9yLmNvZGUgPT09IEVycm9yQ2F0ZWdvcnkuTkVUV09SSyB8fCBcbiAgICAgICAgICAgKGVycm9yLmh0dHBTdGF0dXMgIT09IHVuZGVmaW5lZCAmJiBlcnJvci5odHRwU3RhdHVzID49IDUwMCk7XG4gIH1cbn1cbiJdfQ==