@nauth-toolkit/client-angular 0.1.64 → 0.1.65

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.
@@ -0,0 +1,136 @@
1
+ import { HttpErrorResponse } from '@angular/common/http';
2
+ import { BehaviorSubject, catchError, filter, from, map, of, switchMap, take, throwError } from 'rxjs';
3
+ /**
4
+ * Shared interceptor logic for both:
5
+ * - Functional interceptor (Angular 17+ standalone)
6
+ * - Class-based interceptor (NgModule apps)
7
+ *
8
+ * WHY:
9
+ * - Keep one implementation for cookies + json mode behavior.
10
+ * - Avoid divergence between standalone and NgModule integrations.
11
+ */
12
+ // ============================================================================
13
+ // Refresh state management (module-level)
14
+ // ============================================================================
15
+ let isRefreshing = false;
16
+ const refreshTokenSubject = new BehaviorSubject(null);
17
+ const retriedRequests = new WeakSet();
18
+ /**
19
+ * Get CSRF token from cookie.
20
+ */
21
+ function getCsrfToken(cookieName) {
22
+ if (typeof document === 'undefined')
23
+ return null;
24
+ const match = document.cookie.match(new RegExp(`(^| )${cookieName}=([^;]+)`));
25
+ return match ? decodeURIComponent(match[2]) : null;
26
+ }
27
+ /**
28
+ * Build retry request with appropriate auth.
29
+ *
30
+ * In cookies mode: Browser automatically sends updated httpOnly cookies (access/refresh tokens).
31
+ * We must re-read CSRF token after refresh to avoid stale headers.
32
+ *
33
+ * In JSON mode: Clones the request and adds the new Bearer token.
34
+ */
35
+ function buildRetryRequest(originalReq, tokenDelivery, newToken, csrfConfig) {
36
+ if (tokenDelivery === 'json' && newToken && newToken !== 'success') {
37
+ return originalReq.clone({ setHeaders: { Authorization: `Bearer ${newToken}` } });
38
+ }
39
+ if (tokenDelivery === 'cookies' && ['POST', 'PUT', 'PATCH', 'DELETE'].includes(originalReq.method)) {
40
+ const csrfCookieName = csrfConfig?.cookieName ?? 'nauth_csrf_token';
41
+ const csrfHeaderName = csrfConfig?.headerName ?? 'x-csrf-token';
42
+ const freshCsrfToken = getCsrfToken(csrfCookieName);
43
+ if (freshCsrfToken) {
44
+ return originalReq.clone({ setHeaders: { [csrfHeaderName]: freshCsrfToken } });
45
+ }
46
+ }
47
+ return originalReq;
48
+ }
49
+ export function createNAuthAuthHttpInterceptor(params) {
50
+ const { config, http, authService, router, next, req } = params;
51
+ const tokenDelivery = config.tokenDelivery;
52
+ const baseUrl = config.baseUrl;
53
+ const endpoints = config.endpoints ?? {};
54
+ const refreshPath = endpoints.refresh ?? '/refresh';
55
+ const loginPath = endpoints.login ?? '/login';
56
+ const signupPath = endpoints.signup ?? '/signup';
57
+ const socialExchangePath = endpoints.socialExchange ?? '/social/exchange';
58
+ const refreshUrl = `${baseUrl}${refreshPath}`;
59
+ const isAuthApiRequest = req.url.includes(baseUrl);
60
+ const isRefreshEndpoint = req.url.includes(refreshPath);
61
+ const isPublicEndpoint = req.url.includes(loginPath) || req.url.includes(signupPath) || req.url.includes(socialExchangePath);
62
+ // ============================================================================
63
+ // Build request for cookies mode (withCredentials + CSRF)
64
+ // ============================================================================
65
+ let authReq = req;
66
+ if (tokenDelivery === 'cookies') {
67
+ authReq = authReq.clone({ withCredentials: true });
68
+ if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method)) {
69
+ const csrfCookieName = config.csrf?.cookieName ?? 'nauth_csrf_token';
70
+ const csrfHeaderName = config.csrf?.headerName ?? 'x-csrf-token';
71
+ const csrfToken = getCsrfToken(csrfCookieName);
72
+ if (csrfToken) {
73
+ authReq = authReq.clone({ setHeaders: { [csrfHeaderName]: csrfToken } });
74
+ }
75
+ }
76
+ }
77
+ // ============================================================================
78
+ // JSON mode: attach Authorization header for HttpClient calls
79
+ // ============================================================================
80
+ const attachJsonAuth$ = tokenDelivery === 'json' &&
81
+ isAuthApiRequest &&
82
+ !isRefreshEndpoint &&
83
+ !isPublicEndpoint &&
84
+ !authReq.headers.has('Authorization')
85
+ ? from(authService.getAccessToken()).pipe(map((token) => {
86
+ if (!token)
87
+ return authReq;
88
+ return authReq.clone({ setHeaders: { Authorization: `Bearer ${token}` } });
89
+ }))
90
+ : of(authReq);
91
+ return attachJsonAuth$.pipe(switchMap((requestWithAuth) => next(requestWithAuth).pipe(catchError((error) => {
92
+ const shouldHandle = error instanceof HttpErrorResponse &&
93
+ error.status === 401 &&
94
+ isAuthApiRequest &&
95
+ !isRefreshEndpoint &&
96
+ !isPublicEndpoint &&
97
+ !retriedRequests.has(req);
98
+ if (!shouldHandle) {
99
+ return throwError(() => error);
100
+ }
101
+ retriedRequests.add(req);
102
+ if (!isRefreshing) {
103
+ isRefreshing = true;
104
+ refreshTokenSubject.next(null);
105
+ // Refresh based on mode
106
+ const refresh$ = tokenDelivery === 'cookies'
107
+ ? http.post(refreshUrl, {}, { withCredentials: true })
108
+ : from(authService.refresh());
109
+ return refresh$.pipe(switchMap((response) => {
110
+ isRefreshing = false;
111
+ const newToken = 'accessToken' in response ? response.accessToken : 'success';
112
+ refreshTokenSubject.next(newToken ?? 'success');
113
+ const retryReq = buildRetryRequest(requestWithAuth, tokenDelivery, newToken, config.csrf);
114
+ return next(retryReq).pipe(catchError((retryErr) => {
115
+ return throwError(() => retryErr);
116
+ }));
117
+ }), catchError((err) => {
118
+ isRefreshing = false;
119
+ refreshTokenSubject.next(null);
120
+ // Refresh failed -> redirect if configured
121
+ if (config.redirects?.sessionExpired) {
122
+ router.navigateByUrl(config.redirects.sessionExpired).catch(() => { });
123
+ }
124
+ return throwError(() => err);
125
+ }));
126
+ }
127
+ // Wait for ongoing refresh
128
+ return refreshTokenSubject.pipe(filter((token) => token !== null), take(1), switchMap((token) => {
129
+ const retryReq = buildRetryRequest(requestWithAuth, tokenDelivery, token, config.csrf);
130
+ return next(retryReq).pipe(catchError((retryErr) => {
131
+ return throwError(() => retryErr);
132
+ }));
133
+ }));
134
+ }))));
135
+ }
136
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC1pbnRlcmNlcHRvci5zaGFyZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL2F1dGgtaW50ZXJjZXB0b3Iuc2hhcmVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBYyxpQkFBaUIsRUFBeUMsTUFBTSxzQkFBc0IsQ0FBQztBQUU1RyxPQUFPLEVBQUUsZUFBZSxFQUFjLFVBQVUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFJbkg7Ozs7Ozs7O0dBUUc7QUFFSCwrRUFBK0U7QUFDL0UsMENBQTBDO0FBQzFDLCtFQUErRTtBQUMvRSxJQUFJLFlBQVksR0FBRyxLQUFLLENBQUM7QUFDekIsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLGVBQWUsQ0FBZ0IsSUFBSSxDQUFDLENBQUM7QUFDckUsTUFBTSxlQUFlLEdBQUcsSUFBSSxPQUFPLEVBQXdCLENBQUM7QUFFNUQ7O0dBRUc7QUFDSCxTQUFTLFlBQVksQ0FBQyxVQUFrQjtJQUN0QyxJQUFJLE9BQU8sUUFBUSxLQUFLLFdBQVc7UUFBRSxPQUFPLElBQUksQ0FBQztJQUNqRCxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxRQUFRLFVBQVUsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUM5RSxPQUFPLEtBQUssQ0FBQyxDQUFDLENBQUMsa0JBQWtCLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztBQUNyRCxDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILFNBQVMsaUJBQWlCLENBQ3hCLFdBQWlDLEVBQ2pDLGFBQXFCLEVBQ3JCLFFBQWlCLEVBQ2pCLFVBQXlEO0lBRXpELElBQUksYUFBYSxLQUFLLE1BQU0sSUFBSSxRQUFR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LENBQUMsQ0FDSCxDQUNGLENBQ0YsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBIdHRwQ2xpZW50LCBIdHRwRXJyb3JSZXNwb25zZSwgSHR0cEV2ZW50LCBIdHRwSGFuZGxlckZuLCBIdHRwUmVxdWVzdCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIE9ic2VydmFibGUsIGNhdGNoRXJyb3IsIGZpbHRlciwgZnJvbSwgbWFwLCBvZiwgc3dpdGNoTWFwLCB0YWtlLCB0aHJvd0Vycm9yIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgdHlwZSB7IE5BdXRoQ2xpZW50Q29uZmlnIH0gZnJvbSAnQG5hdXRoLXRvb2xraXQvY2xpZW50JztcbmltcG9ydCB7IEF1dGhTZXJ2aWNlIH0gZnJvbSAnLi4vbmdtb2R1bGUvYXV0aC5zZXJ2aWNlJztcblxuLyoqXG4gKiBTaGFyZWQgaW50ZXJjZXB0b3IgbG9naWMgZm9yIGJvdGg6XG4gKiAtIEZ1bmN0aW9uYWwgaW50ZXJjZXB0b3IgKEFuZ3VsYXIgMTcrIHN0YW5kYWxvbmUpXG4gKiAtIENsYXNzLWJhc2VkIGludGVyY2VwdG9yIChOZ01vZHVsZSBhcHBzKVxuICpcbiAqIFdIWTpcbiAqIC0gS2VlcCBvbmUgaW1wbGVtZW50YXRpb24gZm9yIGNvb2tpZXMgKyBqc29uIG1vZGUgYmVoYXZpb3IuXG4gKiAtIEF2b2lkIGRpdmVyZ2VuY2UgYmV0d2VlbiBzdGFuZGFsb25lIGFuZCBOZ01vZHVsZSBpbnRlZ3JhdGlvbnMuXG4gKi9cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gUmVmcmVzaCBzdGF0ZSBtYW5hZ2VtZW50IChtb2R1bGUtbGV2ZWwpXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5sZXQgaXNSZWZyZXNoaW5nID0gZmFsc2U7XG5jb25zdCByZWZyZXNoVG9rZW5TdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmcgfCBudWxsPihudWxsKTtcbmNvbnN0IHJldHJpZWRSZXF1ZXN0cyA9IG5ldyBXZWFrU2V0PEh0dHBSZXF1ZXN0PHVua25vd24+PigpO1xuXG4vKipcbiAqIEdldCBDU1JGIHRva2VuIGZyb20gY29va2llLlxuICovXG5mdW5jdGlvbiBnZXRDc3JmVG9rZW4oY29va2llTmFtZTogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gIGlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICd1bmRlZmluZWQnKSByZXR1cm4gbnVsbDtcbiAgY29uc3QgbWF0Y2ggPSBkb2N1bWVudC5jb29raWUubWF0Y2gobmV3IFJlZ0V4cChgKF58ICkke2Nvb2tpZU5hbWV9PShbXjtdKylgKSk7XG4gIHJldHVybiBtYXRjaCA/IGRlY29kZVVSSUNvbXBvbmVudChtYXRjaFsyXSkgOiBudWxsO1xufVxuXG4vKipcbiAqIEJ1aWxkIHJldHJ5IHJlcXVlc3Qgd2l0aCBhcHByb3ByaWF0ZSBhdXRoLlxuICpcbiAqIEluIGNvb2tpZXMgbW9kZTogQnJvd3NlciBhdXRvbWF0aWNhbGx5IHNlbmRzIHVwZGF0ZWQgaHR0cE9ubHkgY29va2llcyAoYWNjZXNzL3JlZnJlc2ggdG9rZW5zKS5cbiAqIFdlIG11c3QgcmUtcmVhZCBDU1JGIHRva2VuIGFmdGVyIHJlZnJlc2ggdG8gYXZvaWQgc3RhbGUgaGVhZGVycy5cbiAqXG4gKiBJbiBKU09OIG1vZGU6IENsb25lcyB0aGUgcmVxdWVzdCBhbmQgYWRkcyB0aGUgbmV3IEJlYXJlciB0b2tlbi5cbiAqL1xuZnVuY3Rpb24gYnVpbGRSZXRyeVJlcXVlc3QoXG4gIG9yaWdpbmFsUmVxOiBIdHRwUmVxdWVzdDx1bmtub3duPixcbiAgdG9rZW5EZWxpdmVyeTogc3RyaW5nLFxuICBuZXdUb2tlbj86IHN0cmluZyxcbiAgY3NyZkNvbmZpZz86IHsgY29va2llTmFtZT86IHN0cmluZzsgaGVhZGVyTmFtZT86IHN0cmluZyB9LFxuKTogSHR0cFJlcXVlc3Q8dW5rbm93bj4ge1xuICBpZiAodG9rZW5EZWxpdmVyeSA9PT0gJ2pzb24nICYmIG5ld1Rva2VuICYmIG5ld1Rva2VuICE9PSAnc3VjY2VzcycpIHtcbiAgICByZXR1cm4gb3JpZ2luYWxSZXEuY2xvbmUoeyBzZXRIZWFkZXJzOiB7IEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHtuZXdUb2tlbn1gIH0gfSk7XG4gIH1cblxuICBpZiAodG9rZW5EZWxpdmVyeSA9PT0gJ2Nvb2tpZXMnICYmIFsnUE9TVCcsICdQVVQnLCAnUEFUQ0gnLCAnREVMRVRFJ10uaW5jbHVkZXMob3JpZ2luYWxSZXEubWV0aG9kKSkge1xuICAgIGNvbnN0IGNzcmZDb29raWVOYW1lID0gY3NyZkNvbmZpZz8uY29va2llTmFtZSA/PyAnbmF1dGhfY3NyZl90b2tlbic7XG4gICAgY29uc3QgY3NyZkhlYWRlck5hbWUgPSBjc3JmQ29uZmlnPy5oZWFkZXJOYW1lID8/ICd4LWNzcmYtdG9rZW4nO1xuICAgIGNvbnN0IGZyZXNoQ3NyZlRva2VuID0gZ2V0Q3NyZlRva2VuKGNzcmZDb29raWVOYW1lKTtcbiAgICBpZiAoZnJlc2hDc3JmVG9rZW4pIHtcbiAgICAgIHJldHVybiBvcmlnaW5hbFJlcS5jbG9uZSh7IHNldEhlYWRlcnM6IHsgW2NzcmZIZWFkZXJOYW1lXTogZnJlc2hDc3JmVG9rZW4gfSB9KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gb3JpZ2luYWxSZXE7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVOQXV0aEF1dGhIdHRwSW50ZXJjZXB0b3IocGFyYW1zOiB7XG4gIGNvbmZpZzogTkF1dGhDbGllbnRDb25maWc7XG4gIGh0dHA6IEh0dHBDbGllbnQ7XG4gIGF1dGhTZXJ2aWNlOiBBdXRoU2VydmljZTtcbiAgcm91dGVyOiBSb3V0ZXI7XG4gIG5leHQ6IEh0dHBIYW5kbGVyRm47XG4gIHJlcTogSHR0cFJlcXVlc3Q8dW5rbm93bj47XG59KTogT2JzZXJ2YWJsZTxIdHRwRXZlbnQ8dW5rbm93bj4+IHtcbiAgY29uc3QgeyBjb25maWcsIGh0dHAsIGF1dGhTZXJ2aWNlLCByb3V0ZXIsIG5leHQsIHJlcSB9ID0gcGFyYW1zO1xuXG4gIGNvbnN0IHRva2VuRGVsaXZlcnkgPSBjb25maWcudG9rZW5EZWxpdmVyeTtcbiAgY29uc3QgYmFzZVVybCA9IGNvbmZpZy5iYXNlVXJsO1xuICBjb25zdCBlbmRwb2ludHMgPSBjb25maWcuZW5kcG9pbnRzID8/IHt9O1xuXG4gIGNvbnN0IHJlZnJlc2hQYXRoID0gZW5kcG9pbnRzLnJlZnJlc2ggPz8gJy9yZWZyZXNoJztcbiAgY29uc3QgbG9naW5QYXRoID0gZW5kcG9pbnRzLmxvZ2luID8/ICcvbG9naW4nO1xuICBjb25zdCBzaWdudXBQYXRoID0gZW5kcG9pbnRzLnNpZ251cCA/PyAnL3NpZ251cCc7XG4gIGNvbnN0IHNvY2lhbEV4Y2hhbmdlUGF0aCA9IGVuZHBvaW50cy5zb2NpYWxFeGNoYW5nZSA/PyAnL3NvY2lhbC9leGNoYW5nZSc7XG4gIGNvbnN0IHJlZnJlc2hVcmwgPSBgJHtiYXNlVXJsfSR7cmVmcmVzaFBhdGh9YDtcblxuICBjb25zdCBpc0F1dGhBcGlSZXF1ZXN0ID0gcmVxLnVybC5pbmNsdWRlcyhiYXNlVXJsKTtcbiAgY29uc3QgaXNSZWZyZXNoRW5kcG9pbnQgPSByZXEudXJsLmluY2x1ZGVzKHJlZnJlc2hQYXRoKTtcbiAgY29uc3QgaXNQdWJsaWNFbmRwb2ludCA9XG4gICAgcmVxLnVybC5pbmNsdWRlcyhsb2dpblBhdGgpIHx8IHJlcS51cmwuaW5jbHVkZXMoc2lnbnVwUGF0aCkgfHwgcmVxLnVybC5pbmNsdWRlcyhzb2NpYWxFeGNoYW5nZVBhdGgpO1xuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gQnVpbGQgcmVxdWVzdCBmb3IgY29va2llcyBtb2RlICh3aXRoQ3JlZGVudGlhbHMgKyBDU1JGKVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIGxldCBhdXRoUmVxID0gcmVxO1xuICBpZiAodG9rZW5EZWxpdmVyeSA9PT0gJ2Nvb2tpZXMnKSB7XG4gICAgYXV0aFJlcSA9IGF1dGhSZXEuY2xvbmUoeyB3aXRoQ3JlZGVudGlhbHM6IHRydWUgfSk7XG4gICAgaWYgKFsnUE9TVCcsICdQVVQnLCAnUEFUQ0gnLCAnREVMRVRFJ10uaW5jbHVkZXMocmVxLm1ldGhvZCkpIHtcbiAgICAgIGNvbnN0IGNzcmZDb29raWVOYW1lID0gY29uZmlnLmNzcmY/LmNvb2tpZU5hbWUgPz8gJ25hdXRoX2NzcmZfdG9rZW4nO1xuICAgICAgY29uc3QgY3NyZkhlYWRlck5hbWUgPSBjb25maWcuY3NyZj8uaGVhZGVyTmFtZSA/PyAneC1jc3JmLXRva2VuJztcbiAgICAgIGNvbnN0IGNzcmZUb2tlbiA9IGdldENzcmZUb2tlbihjc3JmQ29va2llTmFtZSk7XG4gICAgICBpZiAoY3NyZlRva2VuKSB7XG4gICAgICAgIGF1dGhSZXEgPSBhdXRoUmVxLmNsb25lKHsgc2V0SGVhZGVyczogeyBbY3NyZkhlYWRlck5hbWVdOiBjc3JmVG9rZW4gfSB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIEpTT04gbW9kZTogYXR0YWNoIEF1dGhvcml6YXRpb24gaGVhZGVyIGZvciBIdHRwQ2xpZW50IGNhbGxzXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgY29uc3QgYXR0YWNoSnNvbkF1dGgkID1cbiAgICB0b2tlbkRlbGl2ZXJ5ID09PSAnanNvbicgJiZcbiAgICBpc0F1dGhBcGlSZXF1ZXN0ICYmXG4gICAgIWlzUmVmcmVzaEVuZHBvaW50ICYmXG4gICAgIWlzUHVibGljRW5kcG9pbnQgJiZcbiAgICAhYXV0aFJlcS5oZWFkZXJzLmhhcygnQXV0aG9yaXphdGlvbicpXG4gICAgICA/IGZyb20oYXV0aFNlcnZpY2UuZ2V0QWNjZXNzVG9rZW4oKSkucGlwZShcbiAgICAgICAgICBtYXAoKHRva2VuKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXRva2VuKSByZXR1cm4gYXV0aFJlcTtcbiAgICAgICAgICAgIHJldHVybiBhdXRoUmVxLmNsb25lKHsgc2V0SGVhZGVyczogeyBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7dG9rZW59YCB9IH0pO1xuICAgICAgICAgIH0pLFxuICAgICAgICApXG4gICAgICA6IG9mKGF1dGhSZXEpO1xuXG4gIHJldHVybiBhdHRhY2hKc29uQXV0aCQucGlwZShcbiAgICBzd2l0Y2hNYXAoKHJlcXVlc3RXaXRoQXV0aCkgPT5cbiAgICAgIG5leHQocmVxdWVzdFdpdGhBdXRoKS5waXBlKFxuICAgICAgICBjYXRjaEVycm9yKChlcnJvcjogdW5rbm93bikgPT4ge1xuICAgICAgICAgIGNvbnN0IHNob3VsZEhhbmRsZSA9XG4gICAgICAgICAgICBlcnJvciBpbnN0YW5jZW9mIEh0dHBFcnJvclJlc3BvbnNlICYmXG4gICAgICAgICAgICBlcnJvci5zdGF0dXMgPT09IDQwMSAmJlxuICAgICAgICAgICAgaXNBdXRoQXBpUmVxdWVzdCAmJlxuICAgICAgICAgICAgIWlzUmVmcmVzaEVuZHBvaW50ICYmXG4gICAgICAgICAgICAhaXNQdWJsaWNFbmRwb2ludCAmJlxuICAgICAgICAgICAgIXJldHJpZWRSZXF1ZXN0cy5oYXMocmVxKTtcblxuICAgICAgICAgIGlmICghc2hvdWxkSGFuZGxlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0cmllZFJlcXVlc3RzLmFkZChyZXEpO1xuXG4gICAgICAgICAgaWYgKCFpc1JlZnJlc2hpbmcpIHtcbiAgICAgICAgICAgIGlzUmVmcmVzaGluZyA9IHRydWU7XG4gICAgICAgICAgICByZWZyZXNoVG9rZW5TdWJqZWN0Lm5leHQobnVsbCk7XG5cbiAgICAgICAgICAgIC8vIFJlZnJlc2ggYmFzZWQgb24gbW9kZVxuICAgICAgICAgICAgY29uc3QgcmVmcmVzaCQgPVxuICAgICAgICAgICAgICB0b2tlbkRlbGl2ZXJ5ID09PSAnY29va2llcydcbiAgICAgICAgICAgICAgICA/IGh0dHAucG9zdDx7IGFjY2Vzc1Rva2VuPzogc3RyaW5nIH0+KHJlZnJlc2hVcmwsIHt9LCB7IHdpdGhDcmVkZW50aWFsczogdHJ1ZSB9KVxuICAgICAgICAgICAgICAgIDogZnJvbShhdXRoU2VydmljZS5yZWZyZXNoKCkpO1xuXG4gICAgICAgICAgICByZXR1cm4gcmVmcmVzaCQucGlwZShcbiAgICAgICAgICAgICAgc3dpdGNoTWFwKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlzUmVmcmVzaGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGNvbnN0IG5ld1Rva2VuID0gJ2FjY2Vzc1Rva2VuJyBpbiByZXNwb25zZSA/IHJlc3BvbnNlLmFjY2Vzc1Rva2VuIDogJ3N1Y2Nlc3MnO1xuICAgICAgICAgICAgICAgIHJlZnJlc2hUb2tlblN1YmplY3QubmV4dChuZXdUb2tlbiA/PyAnc3VjY2VzcycpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgcmV0cnlSZXEgPSBidWlsZFJldHJ5UmVxdWVzdChyZXF1ZXN0V2l0aEF1dGgsIHRva2VuRGVsaXZlcnksIG5ld1Rva2VuLCBjb25maWcuY3NyZik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5leHQocmV0cnlSZXEpLnBpcGUoXG4gICAgICAgICAgICAgICAgICBjYXRjaEVycm9yKChyZXRyeUVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiByZXRyeUVycik7XG4gICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgY2F0Y2hFcnJvcigoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgaXNSZWZyZXNoaW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmVmcmVzaFRva2VuU3ViamVjdC5uZXh0KG51bGwpO1xuXG4gICAgICAgICAgICAgICAgLy8gUmVmcmVzaCBmYWlsZWQgLT4gcmVkaXJlY3QgaWYgY29uZmlndXJlZFxuICAgICAgICAgICAgICAgIGlmIChjb25maWcucmVkaXJlY3RzPy5zZXNzaW9uRXhwaXJlZCkge1xuICAgICAgICAgICAgICAgICAgcm91dGVyLm5hdmlnYXRlQnlVcmwoY29uZmlnLnJlZGlyZWN0cy5zZXNzaW9uRXhwaXJlZCkuY2F0Y2goKCkgPT4ge30pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnIpO1xuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gV2FpdCBmb3Igb25nb2luZyByZWZyZXNoXG4gICAgICAgICAgcmV0dXJuIHJlZnJlc2hUb2tlblN1YmplY3QucGlwZShcbiAgICAgICAgICAgIGZpbHRlcigodG9rZW4pOiB0b2tlbiBpcyBzdHJpbmcgPT4gdG9rZW4gIT09IG51bGwpLFxuICAgICAgICAgICAgdGFrZSgxKSxcbiAgICAgICAgICAgIHN3aXRjaE1hcCgodG9rZW4pID0+IHtcbiAgICAgICAgICAgICAgY29uc3QgcmV0cnlSZXEgPSBidWlsZFJldHJ5UmVxdWVzdChyZXF1ZXN0V2l0aEF1dGgsIHRva2VuRGVsaXZlcnksIHRva2VuLCBjb25maWcuY3NyZik7XG4gICAgICAgICAgICAgIHJldHVybiBuZXh0KHJldHJ5UmVxKS5waXBlKFxuICAgICAgICAgICAgICAgIGNhdGNoRXJyb3IoKHJldHJ5RXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiByZXRyeUVycik7XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICApO1xuICAgICAgICB9KSxcbiAgICAgICksXG4gICAgKSxcbiAgKTtcbn1cbiJdfQ==
@@ -1,29 +1,10 @@
1
1
  import { inject, PLATFORM_ID } from '@angular/core';
2
2
  import { isPlatformBrowser } from '@angular/common';
3
- import { HttpClient, HttpErrorResponse } from '@angular/common/http';
3
+ import { HttpClient } from '@angular/common/http';
4
4
  import { Router } from '@angular/router';
5
- import { catchError, switchMap, throwError, filter, take, BehaviorSubject, from } from 'rxjs';
6
5
  import { NAUTH_CLIENT_CONFIG } from '../ngmodule/tokens';
7
6
  import { AuthService } from '../ngmodule/auth.service';
8
- /**
9
- * Refresh state management.
10
- * BehaviorSubject pattern is the industry-standard for token refresh.
11
- */
12
- let isRefreshing = false;
13
- const refreshTokenSubject = new BehaviorSubject(null);
14
- /**
15
- * Track retried requests to prevent infinite loops.
16
- */
17
- const retriedRequests = new WeakSet();
18
- /**
19
- * Get CSRF token from cookie.
20
- */
21
- function getCsrfToken(cookieName) {
22
- if (typeof document === 'undefined')
23
- return null;
24
- const match = document.cookie.match(new RegExp(`(^| )${cookieName}=([^;]+)`));
25
- return match ? decodeURIComponent(match[2]) : null;
26
- }
7
+ import { createNAuthAuthHttpInterceptor } from './auth-interceptor.shared';
27
8
  /**
28
9
  * Angular HTTP interceptor for nauth-toolkit.
29
10
  *
@@ -41,248 +22,8 @@ export const authInterceptor = (req, next) => {
41
22
  if (!isBrowser) {
42
23
  return next(req);
43
24
  }
44
- // #region agent log
45
- if (req.url.includes('/profile') && req.method === 'PUT') {
46
- fetch('http://127.0.0.1:7242/ingest/97f9fe53-6a8b-43e2-ae9b-4b2d0f725816', {
47
- method: 'POST',
48
- headers: { 'Content-Type': 'application/json' },
49
- body: JSON.stringify({
50
- location: 'auth.interceptor.ts:entry',
51
- message: 'Original request entry',
52
- data: { reqBody: req.body, reqBodyType: typeof req.body, reqMethod: req.method, reqUrl: req.url },
53
- timestamp: Date.now(),
54
- sessionId: 'debug-session',
55
- hypothesisId: 'A',
56
- }),
57
- }).catch(() => { });
58
- }
59
- // #endregion
60
- const tokenDelivery = config.tokenDelivery;
61
- const baseUrl = config.baseUrl;
62
- const endpoints = config.endpoints ?? {};
63
- const refreshPath = endpoints.refresh ?? '/refresh';
64
- const loginPath = endpoints.login ?? '/login';
65
- const signupPath = endpoints.signup ?? '/signup';
66
- const socialExchangePath = endpoints.socialExchange ?? '/social/exchange';
67
- const refreshUrl = `${baseUrl}${refreshPath}`;
68
- const isAuthApiRequest = req.url.includes(baseUrl);
69
- const isRefreshEndpoint = req.url.includes(refreshPath);
70
- const isPublicEndpoint = req.url.includes(loginPath) || req.url.includes(signupPath) || req.url.includes(socialExchangePath);
71
- // Build request with credentials (cookies mode only)
72
- let authReq = req;
73
- if (tokenDelivery === 'cookies') {
74
- authReq = authReq.clone({ withCredentials: true });
75
- if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method)) {
76
- const csrfCookieName = config.csrf?.cookieName ?? 'nauth_csrf_token';
77
- const csrfHeaderName = config.csrf?.headerName ?? 'x-csrf-token';
78
- const csrfToken = getCsrfToken(csrfCookieName);
79
- if (csrfToken) {
80
- authReq = authReq.clone({ setHeaders: { [csrfHeaderName]: csrfToken } });
81
- }
82
- }
83
- }
84
- return next(authReq).pipe(catchError((error) => {
85
- const shouldHandle = error instanceof HttpErrorResponse &&
86
- error.status === 401 &&
87
- isAuthApiRequest &&
88
- !isRefreshEndpoint &&
89
- !isPublicEndpoint &&
90
- !retriedRequests.has(req);
91
- if (!shouldHandle) {
92
- return throwError(() => error);
93
- }
94
- // Mark original request as retried to prevent infinite loops
95
- retriedRequests.add(req);
96
- if (config.debug) {
97
- console.warn('[nauth-interceptor] 401 detected:', req.url);
98
- }
99
- if (!isRefreshing) {
100
- isRefreshing = true;
101
- refreshTokenSubject.next(null);
102
- if (config.debug) {
103
- console.warn('[nauth-interceptor] Starting refresh...');
104
- }
105
- // Refresh based on mode
106
- const refresh$ = tokenDelivery === 'cookies'
107
- ? http.post(refreshUrl, {}, { withCredentials: true })
108
- : from(authService.refresh());
109
- return refresh$.pipe(switchMap((response) => {
110
- if (config.debug) {
111
- console.warn('[nauth-interceptor] Refresh successful');
112
- }
113
- isRefreshing = false;
114
- // Get new token (JSON mode) or signal success (cookies mode)
115
- const newToken = 'accessToken' in response ? response.accessToken : 'success';
116
- refreshTokenSubject.next(newToken ?? 'success');
117
- // #region agent log
118
- fetch('http://127.0.0.1:7242/ingest/97f9fe53-6a8b-43e2-ae9b-4b2d0f725816', {
119
- method: 'POST',
120
- headers: { 'Content-Type': 'application/json' },
121
- body: JSON.stringify({
122
- location: 'auth.interceptor.ts:125',
123
- message: 'Before buildRetryRequest',
124
- data: {
125
- authReqBody: authReq.body,
126
- authReqMethod: authReq.method,
127
- authReqUrl: authReq.url,
128
- authReqBodyType: typeof authReq.body,
129
- },
130
- timestamp: Date.now(),
131
- sessionId: 'debug-session',
132
- hypothesisId: 'A',
133
- }),
134
- }).catch(() => { });
135
- // #endregion
136
- // Build retry request with fresh CSRF token (re-read from cookie after refresh)
137
- const retryReq = buildRetryRequest(authReq, tokenDelivery, newToken, config.csrf);
138
- // #region agent log
139
- fetch('http://127.0.0.1:7242/ingest/97f9fe53-6a8b-43e2-ae9b-4b2d0f725816', {
140
- method: 'POST',
141
- headers: { 'Content-Type': 'application/json' },
142
- body: JSON.stringify({
143
- location: 'auth.interceptor.ts:130',
144
- message: 'After buildRetryRequest',
145
- data: {
146
- retryReqBody: retryReq.body,
147
- retryReqMethod: retryReq.method,
148
- retryReqUrl: retryReq.url,
149
- retryReqBodyType: typeof retryReq.body,
150
- headersKeys: retryReq.headers.keys(),
151
- },
152
- timestamp: Date.now(),
153
- sessionId: 'debug-session',
154
- hypothesisId: 'B',
155
- }),
156
- }).catch(() => { });
157
- // #endregion
158
- if (config.debug) {
159
- console.warn('[nauth-interceptor] Retrying:', req.url);
160
- }
161
- // Retry the request with fresh token/CSRF
162
- // IMPORTANT: Errors from the retry (e.g., 400 validation) should NOT trigger
163
- // session expiration redirect. Only the refresh failure should redirect.
164
- return next(retryReq).pipe(catchError((retryErr) => {
165
- // Retry failed (could be 400, 403, 500, etc.)
166
- // Just propagate the error - don't redirect to login
167
- if (config.debug) {
168
- console.warn('[nauth-interceptor] Retry request failed:', retryErr);
169
- }
170
- return throwError(() => retryErr);
171
- }));
172
- }), catchError((err) => {
173
- // This only catches REFRESH failures, not retry failures
174
- if (config.debug) {
175
- console.error('[nauth-interceptor] Refresh failed:', err);
176
- }
177
- isRefreshing = false;
178
- refreshTokenSubject.next(null);
179
- // Handle session expiration - redirect to configured URL
180
- // Only redirect if refresh itself failed (not if retry failed)
181
- if (config.redirects?.sessionExpired) {
182
- router.navigateByUrl(config.redirects.sessionExpired).catch((navError) => {
183
- if (config.debug) {
184
- console.error('[nauth-interceptor] Navigation failed:', navError);
185
- }
186
- });
187
- }
188
- return throwError(() => err);
189
- }));
190
- }
191
- else {
192
- // Wait for ongoing refresh
193
- if (config.debug) {
194
- console.warn('[nauth-interceptor] Waiting for refresh...');
195
- }
196
- return refreshTokenSubject.pipe(filter((token) => token !== null), take(1), switchMap((token) => {
197
- if (config.debug) {
198
- console.warn('[nauth-interceptor] Refresh done, retrying:', req.url);
199
- }
200
- const retryReq = buildRetryRequest(authReq, tokenDelivery, token, config.csrf);
201
- // Retry the request - errors here should propagate normally
202
- // without triggering session expiration redirect
203
- return next(retryReq).pipe(catchError((retryErr) => {
204
- if (config.debug) {
205
- console.warn('[nauth-interceptor] Retry request failed:', retryErr);
206
- }
207
- return throwError(() => retryErr);
208
- }));
209
- }));
210
- }
211
- }));
25
+ return createNAuthAuthHttpInterceptor({ config, http, authService, router, next, req });
212
26
  };
213
- /**
214
- * Build retry request with appropriate auth.
215
- *
216
- * CRITICAL FIX: In cookies mode, after refresh the server may send updated cookies.
217
- * We MUST re-read the CSRF token from the cookie before retrying to ensure we have
218
- * the current CSRF token that matches what the server expects.
219
- *
220
- * In JSON mode: Clones the request and adds the new Bearer token.
221
- *
222
- * @param originalReq - The base request (already has withCredentials if cookies mode)
223
- * @param tokenDelivery - 'cookies' or 'json'
224
- * @param newToken - The new access token (JSON mode only)
225
- * @param csrfConfig - CSRF configuration to re-read token from cookie
226
- * @returns The request ready for retry with fresh auth
227
- */
228
- function buildRetryRequest(originalReq, tokenDelivery, newToken, csrfConfig) {
229
- if (tokenDelivery === 'json' && newToken && newToken !== 'success') {
230
- return originalReq.clone({
231
- setHeaders: { Authorization: `Bearer ${newToken}` },
232
- });
233
- }
234
- // Cookies mode: Browser automatically sends updated httpOnly cookies (access/refresh tokens).
235
- // However, CSRF token must match the cookie value at the moment of retry.
236
- // We ALWAYS re-read from document.cookie here (using defaults when csrfConfig
237
- // is not provided) to avoid stale header values after refresh or across tabs.
238
- if (tokenDelivery === 'cookies' && ['POST', 'PUT', 'PATCH', 'DELETE'].includes(originalReq.method)) {
239
- const csrfCookieName = csrfConfig?.cookieName ?? 'nauth_csrf_token';
240
- const csrfHeaderName = csrfConfig?.headerName ?? 'x-csrf-token';
241
- const freshCsrfToken = getCsrfToken(csrfCookieName);
242
- // #region agent log
243
- fetch('http://127.0.0.1:7242/ingest/97f9fe53-6a8b-43e2-ae9b-4b2d0f725816', {
244
- method: 'POST',
245
- headers: { 'Content-Type': 'application/json' },
246
- body: JSON.stringify({
247
- location: 'auth.interceptor.ts:buildRetryRequest',
248
- message: 'Inside buildRetryRequest cookies branch',
249
- data: {
250
- originalReqBody: originalReq.body,
251
- originalReqBodyType: typeof originalReq.body,
252
- freshCsrfToken: freshCsrfToken?.substring(0, 8),
253
- method: originalReq.method,
254
- },
255
- timestamp: Date.now(),
256
- sessionId: 'debug-session',
257
- hypothesisId: 'C',
258
- }),
259
- }).catch(() => { });
260
- // #endregion
261
- if (freshCsrfToken) {
262
- // Clone with fresh CSRF token in header
263
- const cloned = originalReq.clone({
264
- setHeaders: { [csrfHeaderName]: freshCsrfToken },
265
- });
266
- // #region agent log
267
- fetch('http://127.0.0.1:7242/ingest/97f9fe53-6a8b-43e2-ae9b-4b2d0f725816', {
268
- method: 'POST',
269
- headers: { 'Content-Type': 'application/json' },
270
- body: JSON.stringify({
271
- location: 'auth.interceptor.ts:buildRetryRequest:afterClone',
272
- message: 'After clone with setHeaders',
273
- data: { clonedBody: cloned.body, clonedBodyType: typeof cloned.body, originalBody: originalReq.body },
274
- timestamp: Date.now(),
275
- sessionId: 'debug-session',
276
- hypothesisId: 'D',
277
- }),
278
- }).catch(() => { });
279
- // #endregion
280
- return cloned;
281
- }
282
- }
283
- // No changes needed (GET request or no CSRF token available)
284
- return originalReq;
285
- }
286
27
  /**
287
28
  * Class-based interceptor for NgModule compatibility.
288
29
  */
@@ -291,4 +32,4 @@ export class AuthInterceptor {
291
32
  return authInterceptor(req, next);
292
33
  }
293
34
  }
294
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5pbnRlcmNlcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvYXV0aC5pbnRlcmNlcHRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNwRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNwRCxPQUFPLEVBQWlELFVBQVUsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3BILE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzlGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUV2RDs7O0dBR0c7QUFDSCxJQUFJLFlBQVksR0FBRyxLQUFLLENBQUM7QUFDekIsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLGVBQWUsQ0FBZ0IsSUFBSSxDQUFDLENBQUM7QUFFckU7O0dBRUc7QUFDSCxNQUFNLGVBQWUsR0FBRyxJQUFJLE9BQU8sRUFBd0IsQ0FBQztBQUU1RDs7R0FFRztBQUNILFNBQVMsWUFBWSxDQUFDLFVBQWtCO0lBQ3RDLElBQUksT0FBTyxRQUFRLEtBQUssV0FBVztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ2pELE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLFFBQVEsVUFBVSxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQzlFLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENB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QUUsVUFBVSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsY0FBYyxFQUFFLE9BQU8sTUFBTSxDQUFDLElBQUksRUFBRSxZQUFZLEVBQUUsV0FBVyxDQUFDLElBQUksRUFBRTtvQkFDckcsU0FBUyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7b0JBQ3JCLFNBQVMsRUFBRSxlQUFlO29CQUMxQixZQUFZLEVBQUUsR0FBRztpQkFDbEIsQ0FBQzthQUNILENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDLENBQUM7WUFDbkIsYUFBYTtZQUViLE9BQU8sTUFBTSxDQUFDO1FBQ2hCLENBQUM7SUFDSCxDQUFDO0lBRUQsNkRBQTZEO0lBQzdELE9BQU8sV0FBVyxDQUFDO0FBQ3JCLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sT0FBTyxlQUFlO0lBQzFCLFNBQVMsQ0FBQyxHQUF5QixFQUFFLElBQW1CO1FBQ3RELE9BQU8sZUFBZSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNwQyxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbmplY3QsIFBMQVRGT1JNX0lEIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBIdHRwSGFuZGxlckZuLCBIdHRwSW50ZXJjZXB0b3JGbiwgSHR0cFJlcXVlc3QsIEh0dHBDbGllbnQsIEh0dHBFcnJvclJlc3BvbnNlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIHN3aXRjaE1hcCwgdGhyb3dFcnJvciwgZmlsdGVyLCB0YWtlLCBCZWhhdmlvclN1YmplY3QsIGZyb20gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IE5BVVRIX0NMSUVOVF9DT05GSUcgfSBmcm9tICcuLi9uZ21vZHVsZS90b2tlbnMnO1xuaW1wb3J0IHsgQXV0aFNlcnZpY2UgfSBmcm9tICcuLi9uZ21vZHVsZS9hdXRoLnNlcnZpY2UnO1xuXG4vKipcbiAqIFJlZnJlc2ggc3RhdGUgbWFuYWdlbWVudC5cbiAqIEJlaGF2aW9yU3ViamVjdCBwYXR0ZXJuIGlzIHRoZSBpbmR1c3RyeS1zdGFuZGFyZCBmb3IgdG9rZW4gcmVmcmVzaC5cbiAqL1xubGV0IGlzUmVmcmVzaGluZyA9IGZhbHNlO1xuY29uc3QgcmVmcmVzaFRva2VuU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8c3RyaW5nIHwgbnVsbD4obnVsbCk7XG5cbi8qKlxuICogVHJhY2sgcmV0cmllZCByZXF1ZXN0cyB0byBwcmV2ZW50IGluZmluaXRlIGxvb3BzLlxuICovXG5jb25zdCByZXRyaWVkUmVxdWVzdHMgPSBuZXcgV2Vha1NldDxIdHRwUmVxdWVzdDx1bmtub3duPj4oKTtcblxuLyoqXG4gKiBHZXQgQ1NSRiB0b2tlbiBmcm9tIGNvb2tpZS5cbiAqL1xuZnVuY3Rpb24gZ2V0Q3NyZlRva2VuKGNvb2tpZU5hbWU6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICBpZiAodHlwZW9mIGRvY3VtZW50ID09PSAndW5kZWZpbmVkJykgcmV0dXJuIG51bGw7XG4gIGNvbnN0IG1hdGNoID0gZG9jdW1lbnQuY29va2llLm1hdGNoKG5ldyBSZWdFeHAoYChefCApJHtjb29raWVOYW1lfT0oW147XSspYCkpO1xuICByZXR1cm4gbWF0Y2ggPyBkZWNvZGVVUklDb21wb25lbnQobWF0Y2hbMl0pIDogbnVsbDtcbn1cblxuLyoqXG4gKiBBbmd1bGFyIEhUVFAgaW50ZXJjZXB0b3IgZm9yIG5hdXRoLXRvb2xraXQuXG4gKlxuICogSGFuZGxlczpcbiAqIC0gQ29va2llcyBtb2RlOiB3aXRoQ3JlZGVudGlhbHMgKyBDU1JGIHRva2VucyArIHJlZnJlc2ggdmlhIFBPU1RcbiAqIC0gSlNPTiBtb2RlOiByZWZyZXNoIHZpYSBTREssIHJldHJ5IHdpdGggbmV3IHRva2VuXG4gKi9cbmV4cG9ydCBjb25zdCBhdXRoSW50ZXJjZXB0b3I6IEh0dHBJbnRlcmNlcHRvckZuID0gKHJlcTogSHR0cFJlcXVlc3Q8dW5rbm93bj4sIG5leHQ6IEh0dHBIYW5kbGVyRm4pID0+IHtcbiAgY29uc3QgY29uZmlnID0gaW5qZWN0KE5BVVRIX0NMSUVOVF9DT05GSUcpO1xuICBjb25zdCBodHRwID0gaW5qZWN0KEh0dHBDbGllbnQpO1xuICBjb25zdCBhdXRoU2VydmljZSA9IGluamVjdChBdXRoU2VydmljZSk7XG4gIGNvbnN0IHBsYXRmb3JtSWQgPSBpbmplY3QoUExBVEZPUk1fSUQpO1xuICBjb25zdCByb3V0ZXIgPSBpbmplY3QoUm91dGVyKTtcbiAgY29uc3QgaXNCcm93c2VyID0gaXNQbGF0Zm9ybUJyb3dzZXIocGxhdGZvcm1JZCk7XG5cbiAgaWYgKCFpc0Jyb3dzZXIpIHtcbiAgICByZXR1cm4gbmV4dChyZXEpO1xuICB9XG5cbiAgLy8gI3JlZ2lvbiBhZ2VudCBsb2dcbiAgaWYgKHJlcS51cmwuaW5jbHVkZXMoJy9wcm9maWxlJykgJiYgcmVxLm1ldGhvZCA9PT0gJ1BVVCcpIHtcbiAgICBmZXRjaCgnaHR0cDovLzEyNy4wLjAuMTo3MjQyL2luZ2VzdC85N2Y5ZmU1My02YThiLTQzZTItYWU5Yi00YjJkMGY3MjU4MTYnLCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9LFxuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICBsb2NhdGlvbjogJ2F1dGguaW50ZXJjZXB0b3IudHM6ZW50cnknLFxuICAgICAgICBtZXNzYWdlOiAnT3JpZ2luYWwgcmVxdWVzdCBlbnRyeScsXG4gICAgICAgIGRhdGE6IHsgcmVxQm9keTogcmVxLmJvZHksIHJlcUJvZHlUeXBlOiB0eXBlb2YgcmVxLmJvZHksIHJlcU1ldGhvZDogcmVxLm1ldGhvZCwgcmVxVXJsOiByZXEudXJsIH0sXG4gICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgICAgc2Vzc2lvbklkOiAnZGVidWctc2Vzc2lvbicsXG4gICAgICAgIGh5cG90aGVzaXNJZDogJ0EnLFxuICAgICAgfSksXG4gICAgfSkuY2F0Y2goKCkgPT4ge30pO1xuICB9XG4gIC8vICNlbmRyZWdpb25cblxuICBjb25zdCB0b2tlbkRlbGl2ZXJ5ID0gY29uZmlnLnRva2VuRGVsaXZlcnk7XG4gIGNvbnN0IGJhc2VVcmwgPSBjb25maWcuYmFzZVVybDtcbiAgY29uc3QgZW5kcG9pbnRzID0gY29uZmlnLmVuZHBvaW50cyA/PyB7fTtcbiAgY29uc3QgcmVmcmVzaFBhdGggPSBlbmRwb2ludHMucmVmcmVzaCA/PyAnL3JlZnJlc2gnO1xuICBjb25zdCBsb2dpblBhdGggPSBlbmRwb2ludHMubG9naW4gPz8gJy9sb2dpbic7XG4gIGNvbnN0IHNpZ251cFBhdGggPSBlbmRwb2ludHMuc2lnbnVwID8/ICcvc2lnbnVwJztcbiAgY29uc3Qgc29jaWFsRXhjaGFuZ2VQYXRoID0gZW5kcG9pbnRzLnNvY2lhbEV4Y2hhbmdlID8/ICcvc29jaWFsL2V4Y2hhbmdlJztcbiAgY29uc3QgcmVmcmVzaFVybCA9IGAke2Jhc2VVcmx9JHtyZWZyZXNoUGF0aH1gO1xuXG4gIGNvbnN0IGlzQXV0aEFwaVJlcXVlc3QgPSByZXEudXJsLmluY2x1ZGVzKGJhc2VVcmwpO1xuICBjb25zdCBpc1JlZnJlc2hFbmRwb2ludCA9IHJlcS51cmwuaW5jbHVkZXMocmVmcmVzaFBhdGgpO1xuICBjb25zdCBpc1B1YmxpY0VuZHBvaW50ID1cbiAgICByZXEudXJsLmluY2x1ZGVzKGxvZ2luUGF0aCkgfHwgcmVxLnVybC5pbmNsdWRlcyhzaWdudXBQYXRoKSB8fCByZXEudXJsLmluY2x1ZGVzKHNvY2lhbEV4Y2hhbmdlUGF0aCk7XG5cbiAgLy8gQnVpbGQgcmVxdWVzdCB3aXRoIGNyZWRlbnRpYWxzIChjb29raWVzIG1vZGUgb25seSlcbiAgbGV0IGF1dGhSZXEgPSByZXE7XG4gIGlmICh0b2tlbkRlbGl2ZXJ5ID09PSAnY29va2llcycpIHtcbiAgICBhdXRoUmVxID0gYXV0aFJlcS5jbG9uZSh7IHdpdGhDcmVkZW50aWFsczogdHJ1ZSB9KTtcblxuICAgIGlmIChbJ1BPU1QnLCAnUFVUJywgJ1BBVENIJywgJ0RFTEVURSddLmluY2x1ZGVzKHJlcS5tZXRob2QpKSB7XG4gICAgICBjb25zdCBjc3JmQ29va2llTmFtZSA9IGNvbmZpZy5jc3JmPy5jb29raWVOYW1lID8/ICduYXV0aF9jc3JmX3Rva2VuJztcbiAgICAgIGNvbnN0IGNzcmZIZWFkZXJOYW1lID0gY29uZmlnLmNzcmY/LmhlYWRlck5hbWUgPz8gJ3gtY3NyZi10b2tlbic7XG4gICAgICBjb25zdCBjc3JmVG9rZW4gPSBnZXRDc3JmVG9rZW4oY3NyZkNvb2tpZU5hbWUpO1xuICAgICAgaWYgKGNzcmZUb2tlbikge1xuICAgICAgICBhdXRoUmVxID0gYXV0aFJlcS5jbG9uZSh7IHNldEhlYWRlcnM6IHsgW2NzcmZIZWFkZXJOYW1lXTogY3NyZlRva2VuIH0gfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5leHQoYXV0aFJlcSkucGlwZShcbiAgICBjYXRjaEVycm9yKChlcnJvcjogdW5rbm93bikgPT4ge1xuICAgICAgY29uc3Qgc2hvdWxkSGFuZGxlID1cbiAgICAgICAgZXJyb3IgaW5zdGFuY2VvZiBIdHRwRXJyb3JSZXNwb25zZSAmJlxuICAgICAgICBlcnJvci5zdGF0dXMgPT09IDQwMSAmJlxuICAgICAgICBpc0F1dGhBcGlSZXF1ZXN0ICYmXG4gICAgICAgICFpc1JlZnJlc2hFbmRwb2ludCAmJlxuICAgICAgICAhaXNQdWJsaWNFbmRwb2ludCAmJlxuICAgICAgICAhcmV0cmllZFJlcXVlc3RzLmhhcyhyZXEpO1xuXG4gICAgICBpZiAoIXNob3VsZEhhbmRsZSkge1xuICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XG4gICAgICB9XG5cbiAgICAgIC8vIE1hcmsgb3JpZ2luYWwgcmVxdWVzdCBhcyByZXRyaWVkIHRvIHByZXZlbnQgaW5maW5pdGUgbG9vcHNcbiAgICAgIHJldHJpZWRSZXF1ZXN0cy5hZGQocmVxKTtcblxuICAgICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgICBjb25zb2xlLndhcm4oJ1tuYXV0aC1pbnRlcmNlcHRvcl0gNDAxIGRldGVjdGVkOicsIHJlcS51cmwpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWlzUmVmcmVzaGluZykge1xuICAgICAgICBpc1JlZnJlc2hpbmcgPSB0cnVlO1xuICAgICAgICByZWZyZXNoVG9rZW5TdWJqZWN0Lm5leHQobnVsbCk7XG5cbiAgICAgICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgICAgIGNvbnNvbGUud2FybignW25hdXRoLWludGVyY2VwdG9yXSBTdGFydGluZyByZWZyZXNoLi4uJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZWZyZXNoIGJhc2VkIG9uIG1vZGVcbiAgICAgICAgY29uc3QgcmVmcmVzaCQgPVxuICAgICAgICAgIHRva2VuRGVsaXZlcnkgPT09ICdjb29raWVzJ1xuICAgICAgICAgICAgPyBodHRwLnBvc3Q8eyBhY2Nlc3NUb2tlbj86IHN0cmluZyB9PihyZWZyZXNoVXJsLCB7fSwgeyB3aXRoQ3JlZGVudGlhbHM6IHRydWUgfSlcbiAgICAgICAgICAgIDogZnJvbShhdXRoU2VydmljZS5yZWZyZXNoKCkpO1xuXG4gICAgICAgIHJldHVybiByZWZyZXNoJC5waXBlKFxuICAgICAgICAgIHN3aXRjaE1hcCgocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdbbmF1dGgtaW50ZXJjZXB0b3JdIFJlZnJlc2ggc3VjY2Vzc2Z1bCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaXNSZWZyZXNoaW5nID0gZmFsc2U7XG5cbiAgICAgICAgICAgIC8vIEdldCBuZXcgdG9rZW4gKEpTT04gbW9kZSkgb3Igc2lnbmFsIHN1Y2Nlc3MgKGNvb2tpZXMgbW9kZSlcbiAgICAgICAgICAgIGNvbnN0IG5ld1Rva2VuID0gJ2FjY2Vzc1Rva2VuJyBpbiByZXNwb25zZSA/IHJlc3BvbnNlLmFjY2Vzc1Rva2VuIDogJ3N1Y2Nlc3MnO1xuICAgICAgICAgICAgcmVmcmVzaFRva2VuU3ViamVjdC5uZXh0KG5ld1Rva2VuID8/ICdzdWNjZXNzJyk7XG5cbiAgICAgICAgICAgIC8vICNyZWdpb24gYWdlbnQgbG9nXG4gICAgICAgICAgICBmZXRjaCgnaHR0cDovLzEyNy4wLjAuMTo3MjQyL2luZ2VzdC85N2Y5ZmU1My02YThiLTQzZTItYWU5Yi00YjJkMGY3MjU4MTYnLCB7XG4gICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICBoZWFkZXJzOiB7ICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicgfSxcbiAgICAgICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgIGxvY2F0aW9uOiAnYXV0aC5pbnRlcmNlcHRvci50czoxMjUnLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6ICdCZWZvcmUgYnVpbGRSZXRyeVJlcXVlc3QnLFxuICAgICAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICAgIGF1dGhSZXFCb2R5OiBhdXRoUmVxLmJvZHksXG4gICAgICAgICAgICAgICAgICBhdXRoUmVxTWV0aG9kOiBhdXRoUmVxLm1ldGhvZCxcbiAgICAgICAgICAgICAgICAgIGF1dGhSZXFVcmw6IGF1dGhSZXEudXJsLFxuICAgICAgICAgICAgICAgICAgYXV0aFJlcUJvZHlUeXBlOiB0eXBlb2YgYXV0aFJlcS5ib2R5LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgICAgIHNlc3Npb25JZDogJ2RlYnVnLXNlc3Npb24nLFxuICAgICAgICAgICAgICAgIGh5cG90aGVzaXNJZDogJ0EnLFxuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIH0pLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgICAgICAgIC8vICNlbmRyZWdpb25cblxuICAgICAgICAgICAgLy8gQnVpbGQgcmV0cnkgcmVxdWVzdCB3aXRoIGZyZXNoIENTUkYgdG9rZW4gKHJlLXJlYWQgZnJvbSBjb29raWUgYWZ0ZXIgcmVmcmVzaClcbiAgICAgICAgICAgIGNvbnN0IHJldHJ5UmVxID0gYnVpbGRSZXRyeVJlcXVlc3QoYXV0aFJlcSwgdG9rZW5EZWxpdmVyeSwgbmV3VG9rZW4sIGNvbmZpZy5jc3JmKTtcblxuICAgICAgICAgICAgLy8gI3JlZ2lvbiBhZ2VudCBsb2dcbiAgICAgICAgICAgIGZldGNoKCdodHRwOi8vMTI3LjAuMC4xOjcyNDIvaW5nZXN0Lzk3ZjlmZTUzLTZhOGItNDNlMi1hZTliLTRiMmQwZjcyNTgxNicsIHtcbiAgICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9LFxuICAgICAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgbG9jYXRpb246ICdhdXRoLmludGVyY2VwdG9yLnRzOjEzMCcsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogJ0FmdGVyIGJ1aWxkUmV0cnlSZXF1ZXN0JyxcbiAgICAgICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgICByZXRyeVJlcUJvZHk6IHJldHJ5UmVxLmJvZHksXG4gICAgICAgICAgICAgICAgICByZXRyeVJlcU1ldGhvZDogcmV0cnlSZXEubWV0aG9kLFxuICAgICAgICAgICAgICAgICAgcmV0cnlSZXFVcmw6IHJldHJ5UmVxLnVybCxcbiAgICAgICAgICAgICAgICAgIHJldHJ5UmVxQm9keVR5cGU6IHR5cGVvZiByZXRyeVJlcS5ib2R5LFxuICAgICAgICAgICAgICAgICAgaGVhZGVyc0tleXM6IHJldHJ5UmVxLmhlYWRlcnMua2V5cygpLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgICAgIHNlc3Npb25JZDogJ2RlYnVnLXNlc3Npb24nLFxuICAgICAgICAgICAgICAgIGh5cG90aGVzaXNJZDogJ0InLFxuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIH0pLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgICAgICAgIC8vICNlbmRyZWdpb25cblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tuYXV0aC1pbnRlcmNlcHRvcl0gUmV0cnlpbmc6JywgcmVxLnVybCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFJldHJ5IHRoZSByZXF1ZXN0IHdpdGggZnJlc2ggdG9rZW4vQ1NSRlxuICAgICAgICAgICAgLy8gSU1QT1JUQU5UOiBFcnJvcnMgZnJvbSB0aGUgcmV0cnkgKGUuZy4sIDQwMCB2YWxpZGF0aW9uKSBzaG91bGQgTk9UIHRyaWdnZXJcbiAgICAgICAgICAgIC8vIHNlc3Npb24gZXhwaXJhdGlvbiByZWRpcmVjdC4gT25seSB0aGUgcmVmcmVzaCBmYWlsdXJlIHNob3VsZCByZWRpcmVjdC5cbiAgICAgICAgICAgIHJldHVybiBuZXh0KHJldHJ5UmVxKS5waXBlKFxuICAgICAgICAgICAgICBjYXRjaEVycm9yKChyZXRyeUVycikgPT4ge1xuICAgICAgICAgICAgICAgIC8vIFJldHJ5IGZhaWxlZCAoY291bGQgYmUgNDAwLCA0MDMsIDUwMCwgZXRjLilcbiAgICAgICAgICAgICAgICAvLyBKdXN0IHByb3BhZ2F0ZSB0aGUgZXJyb3IgLSBkb24ndCByZWRpcmVjdCB0byBsb2dpblxuICAgICAgICAgICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignW25hdXRoLWludGVyY2VwdG9yXSBSZXRyeSByZXF1ZXN0IGZhaWxlZDonLCByZXRyeUVycik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IHJldHJ5RXJyKTtcbiAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pLFxuICAgICAgICAgIGNhdGNoRXJyb3IoKGVycikgPT4ge1xuICAgICAgICAgICAgLy8gVGhpcyBvbmx5IGNhdGNoZXMgUkVGUkVTSCBmYWlsdXJlcywgbm90IHJldHJ5IGZhaWx1cmVzXG4gICAgICAgICAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1tuYXV0aC1pbnRlcmNlcHRvcl0gUmVmcmVzaCBmYWlsZWQ6JywgZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlzUmVmcmVzaGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmVmcmVzaFRva2VuU3ViamVjdC5uZXh0KG51bGwpO1xuXG4gICAgICAgICAgICAvLyBIYW5kbGUgc2Vzc2lvbiBleHBpcmF0aW9uIC0gcmVkaXJlY3QgdG8gY29uZmlndXJlZCBVUkxcbiAgICAgICAgICAgIC8vIE9ubHkgcmVkaXJlY3QgaWYgcmVmcmVzaCBpdHNlbGYgZmFpbGVkIChub3QgaWYgcmV0cnkgZmFpbGVkKVxuICAgICAgICAgICAgaWYgKGNvbmZpZy5yZWRpcmVjdHM/LnNlc3Npb25FeHBpcmVkKSB7XG4gICAgICAgICAgICAgIHJvdXRlci5uYXZpZ2F0ZUJ5VXJsKGNvbmZpZy5yZWRpcmVjdHMuc2Vzc2lvbkV4cGlyZWQpLmNhdGNoKChuYXZFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1tuYXV0aC1pbnRlcmNlcHRvcl0gTmF2aWdhdGlvbiBmYWlsZWQ6JywgbmF2RXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGVycik7XG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBXYWl0IGZvciBvbmdvaW5nIHJlZnJlc2hcbiAgICAgICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgICAgIGNvbnNvbGUud2FybignW25hdXRoLWludGVyY2VwdG9yXSBXYWl0aW5nIGZvciByZWZyZXNoLi4uJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlZnJlc2hUb2tlblN1YmplY3QucGlwZShcbiAgICAgICAgICBmaWx0ZXIoKHRva2VuKTogdG9rZW4gaXMgc3RyaW5nID0+IHRva2VuICE9PSBudWxsKSxcbiAgICAgICAgICB0YWtlKDEpLFxuICAgICAgICAgIHN3aXRjaE1hcCgodG9rZW4pID0+IHtcbiAgICAgICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdbbmF1dGgtaW50ZXJjZXB0b3JdIFJlZnJlc2ggZG9uZSwgcmV0cnlpbmc6JywgcmVxLnVybCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXRyeVJlcSA9IGJ1aWxkUmV0cnlSZXF1ZXN0KGF1dGhSZXEsIHRva2VuRGVsaXZlcnksIHRva2VuLCBjb25maWcuY3NyZik7XG5cbiAgICAgICAgICAgIC8vIFJldHJ5IHRoZSByZXF1ZXN0IC0gZXJyb3JzIGhlcmUgc2hvdWxkIHByb3BhZ2F0ZSBub3JtYWxseVxuICAgICAgICAgICAgLy8gd2l0aG91dCB0cmlnZ2VyaW5nIHNlc3Npb24gZXhwaXJhdGlvbiByZWRpcmVjdFxuICAgICAgICAgICAgcmV0dXJuIG5leHQocmV0cnlSZXEpLnBpcGUoXG4gICAgICAgICAgICAgIGNhdGNoRXJyb3IoKHJldHJ5RXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdbbmF1dGgtaW50ZXJjZXB0b3JdIFJldHJ5IHJlcXVlc3QgZmFpbGVkOicsIHJldHJ5RXJyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gcmV0cnlFcnIpO1xuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSksXG4gICk7XG59O1xuXG4vKipcbiAqIEJ1aWxkIHJldHJ5IHJlcXVlc3Qgd2l0aCBhcHByb3ByaWF0ZSBhdXRoLlxuICpcbiAqIENSSVRJQ0FMIEZJWDogSW4gY29va2llcyBtb2RlLCBhZnRlciByZWZyZXNoIHRoZSBzZXJ2ZXIgbWF5IHNlbmQgdXBkYXRlZCBjb29raWVzLlxuICogV2UgTVVTVCByZS1yZWFkIHRoZSBDU1JGIHRva2VuIGZyb20gdGhlIGNvb2tpZSBiZWZvcmUgcmV0cnlpbmcgdG8gZW5zdXJlIHdlIGhhdmVcbiAqIHRoZSBjdXJyZW50IENTUkYgdG9rZW4gdGhhdCBtYXRjaGVzIHdoYXQgdGhlIHNlcnZlciBleHBlY3RzLlxuICpcbiAqIEluIEpTT04gbW9kZTogQ2xvbmVzIHRoZSByZXF1ZXN0IGFuZCBhZGRzIHRoZSBuZXcgQmVhcmVyIHRva2VuLlxuICpcbiAqIEBwYXJhbSBvcmlnaW5hbFJlcSAtIFRoZSBiYXNlIHJlcXVlc3QgKGFscmVhZHkgaGFzIHdpdGhDcmVkZW50aWFscyBpZiBjb29raWVzIG1vZGUpXG4gKiBAcGFyYW0gdG9rZW5EZWxpdmVyeSAtICdjb29raWVzJyBvciAnanNvbidcbiAqIEBwYXJhbSBuZXdUb2tlbiAtIFRoZSBuZXcgYWNjZXNzIHRva2VuIChKU09OIG1vZGUgb25seSlcbiAqIEBwYXJhbSBjc3JmQ29uZmlnIC0gQ1NSRiBjb25maWd1cmF0aW9uIHRvIHJlLXJlYWQgdG9rZW4gZnJvbSBjb29raWVcbiAqIEByZXR1cm5zIFRoZSByZXF1ZXN0IHJlYWR5IGZvciByZXRyeSB3aXRoIGZyZXNoIGF1dGhcbiAqL1xuZnVuY3Rpb24gYnVpbGRSZXRyeVJlcXVlc3QoXG4gIG9yaWdpbmFsUmVxOiBIdHRwUmVxdWVzdDx1bmtub3duPixcbiAgdG9rZW5EZWxpdmVyeTogc3RyaW5nLFxuICBuZXdUb2tlbj86IHN0cmluZyxcbiAgY3NyZkNvbmZpZz86IHsgY29va2llTmFtZT86IHN0cmluZzsgaGVhZGVyTmFtZT86IHN0cmluZyB9LFxuKTogSHR0cFJlcXVlc3Q8dW5rbm93bj4ge1xuICBpZiAodG9rZW5EZWxpdmVyeSA9PT0gJ2pzb24nICYmIG5ld1Rva2VuICYmIG5ld1Rva2VuICE9PSAnc3VjY2VzcycpIHtcbiAgICByZXR1cm4gb3JpZ2luYWxSZXEuY2xvbmUoe1xuICAgICAgc2V0SGVhZGVyczogeyBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7bmV3VG9rZW59YCB9LFxuICAgIH0pO1xuICB9XG5cbiAgLy8gQ29va2llcyBtb2RlOiBCcm93c2VyIGF1dG9tYXRpY2FsbHkgc2VuZHMgdXBkYXRlZCBodHRwT25seSBjb29raWVzIChhY2Nlc3MvcmVmcmVzaCB0b2tlbnMpLlxuICAvLyBIb3dldmVyLCBDU1JGIHRva2VuIG11c3QgbWF0Y2ggdGhlIGNvb2tpZSB2YWx1ZSBhdCB0aGUgbW9tZW50IG9mIHJldHJ5LlxuICAvLyBXZSBBTFdBWVMgcmUtcmVhZCBmcm9tIGRvY3VtZW50LmNvb2tpZSBoZXJlICh1c2luZyBkZWZhdWx0cyB3aGVuIGNzcmZDb25maWdcbiAgLy8gaXMgbm90IHByb3ZpZGVkKSB0byBhdm9pZCBzdGFsZSBoZWFkZXIgdmFsdWVzIGFmdGVyIHJlZnJlc2ggb3IgYWNyb3NzIHRhYnMuXG4gIGlmICh0b2tlbkRlbGl2ZXJ5ID09PSAnY29va2llcycgJiYgWydQT1NUJywgJ1BVVCcsICdQQVRDSCcsICdERUxFVEUnXS5pbmNsdWRlcyhvcmlnaW5hbFJlcS5tZXRob2QpKSB7XG4gICAgY29uc3QgY3NyZkNvb2tpZU5hbWUgPSBjc3JmQ29uZmlnPy5jb29raWVOYW1lID8/ICduYXV0aF9jc3JmX3Rva2VuJztcbiAgICBjb25zdCBjc3JmSGVhZGVyTmFtZSA9IGNzcmZDb25maWc/LmhlYWRlck5hbWUgPz8gJ3gtY3NyZi10b2tlbic7XG4gICAgY29uc3QgZnJlc2hDc3JmVG9rZW4gPSBnZXRDc3JmVG9rZW4oY3NyZkNvb2tpZU5hbWUpO1xuXG4gICAgLy8gI3JlZ2lvbiBhZ2VudCBsb2dcbiAgICBmZXRjaCgnaHR0cDovLzEyNy4wLjAuMTo3MjQyL2luZ2VzdC85N2Y5ZmU1My02YThiLTQzZTItYWU5Yi00YjJkMGY3MjU4MTYnLCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9LFxuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICBsb2NhdGlvbjogJ2F1dGguaW50ZXJjZXB0b3IudHM6YnVpbGRSZXRyeVJlcXVlc3QnLFxuICAgICAgICBtZXNzYWdlOiAnSW5zaWRlIGJ1aWxkUmV0cnlSZXF1ZXN0IGNvb2tpZXMgYnJhbmNoJyxcbiAgICAgICAgZGF0YToge1xuICAgICAgICAgIG9yaWdpbmFsUmVxQm9keTogb3JpZ2luYWxSZXEuYm9keSxcbiAgICAgICAgICBvcmlnaW5hbFJlcUJvZHlUeXBlOiB0eXBlb2Ygb3JpZ2luYWxSZXEuYm9keSxcbiAgICAgICAgICBmcmVzaENzcmZUb2tlbjogZnJlc2hDc3JmVG9rZW4/LnN1YnN0cmluZygwLCA4KSxcbiAgICAgICAgICBtZXRob2Q6IG9yaWdpbmFsUmVxLm1ldGhvZCxcbiAgICAgICAgfSxcbiAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICBzZXNzaW9uSWQ6ICdkZWJ1Zy1zZXNzaW9uJyxcbiAgICAgICAgaHlwb3RoZXNpc0lkOiAnQycsXG4gICAgICB9KSxcbiAgICB9KS5jYXRjaCgoKSA9PiB7fSk7XG4gICAgLy8gI2VuZHJlZ2lvblxuXG4gICAgaWYgKGZyZXNoQ3NyZlRva2VuKSB7XG4gICAgICAvLyBDbG9uZSB3aXRoIGZyZXNoIENTUkYgdG9rZW4gaW4gaGVhZGVyXG4gICAgICBjb25zdCBjbG9uZWQgPSBvcmlnaW5hbFJlcS5jbG9uZSh7XG4gICAgICAgIHNldEhlYWRlcnM6IHsgW2NzcmZIZWFkZXJOYW1lXTogZnJlc2hDc3JmVG9rZW4gfSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyAjcmVnaW9uIGFnZW50IGxvZ1xuICAgICAgZmV0Y2goJ2h0dHA6Ly8xMjcuMC4wLjE6NzI0Mi9pbmdlc3QvOTdmOWZlNTMtNmE4Yi00M2UyLWFlOWItNGIyZDBmNzI1ODE2Jywge1xuICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nIH0sXG4gICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICBsb2NhdGlvbjogJ2F1dGguaW50ZXJjZXB0b3IudHM6YnVpbGRSZXRyeVJlcXVlc3Q6YWZ0ZXJDbG9uZScsXG4gICAgICAgICAgbWVzc2FnZTogJ0FmdGVyIGNsb25lIHdpdGggc2V0SGVhZGVycycsXG4gICAgICAgICAgZGF0YTogeyBjbG9uZWRCb2R5OiBjbG9uZWQuYm9keSwgY2xvbmVkQm9keVR5cGU6IHR5cGVvZiBjbG9uZWQuYm9keSwgb3JpZ2luYWxCb2R5OiBvcmlnaW5hbFJlcS5ib2R5IH0sXG4gICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgIHNlc3Npb25JZDogJ2RlYnVnLXNlc3Npb24nLFxuICAgICAgICAgIGh5cG90aGVzaXNJZDogJ0QnLFxuICAgICAgICB9KSxcbiAgICAgIH0pLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgIC8vICNlbmRyZWdpb25cblxuICAgICAgcmV0dXJuIGNsb25lZDtcbiAgICB9XG4gIH1cblxuICAvLyBObyBjaGFuZ2VzIG5lZWRlZCAoR0VUIHJlcXVlc3Qgb3Igbm8gQ1NSRiB0b2tlbiBhdmFpbGFibGUpXG4gIHJldHVybiBvcmlnaW5hbFJlcTtcbn1cblxuLyoqXG4gKiBDbGFzcy1iYXNlZCBpbnRlcmNlcHRvciBmb3IgTmdNb2R1bGUgY29tcGF0aWJpbGl0eS5cbiAqL1xuZXhwb3J0IGNsYXNzIEF1dGhJbnRlcmNlcHRvciB7XG4gIGludGVyY2VwdChyZXE6IEh0dHBSZXF1ZXN0PHVua25vd24+LCBuZXh0OiBIdHRwSGFuZGxlckZuKSB7XG4gICAgcmV0dXJuIGF1dGhJbnRlcmNlcHRvcihyZXEsIG5leHQpO1xuICB9XG59XG4iXX0=
35
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5pbnRlcmNlcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvYXV0aC5pbnRlcmNlcHRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNwRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNwRCxPQUFPLEVBQWlELFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2pHLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN6RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDdkQsT0FBTyxFQUFFLDhCQUE4QixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFM0U7Ozs7OztHQU1HO0FBQ0gsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFzQixDQUFDLEdBQXlCLEVBQUUsSUFBbUIsRUFBRSxFQUFFO0lBQ25HLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBQzNDLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNoQyxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDeEMsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3ZDLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM5QixNQUFNLFNBQVMsR0FBRyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUVoRCxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDZixPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuQixDQUFDO0lBRUQsT0FBTyw4QkFBOEIsQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztBQUMxRixDQUFDLENBQUM7QUFFRjs7R0FFRztBQUNILE1BQU0sT0FBTyxlQUFlO0lBQzFCLFNBQVMsQ0FBQyxHQUF5QixFQUFFLElBQW1CO1FBQ3RELE9BQU8sZUFBZSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNwQyxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbmplY3QsIFBMQVRGT1JNX0lEIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBIdHRwSGFuZGxlckZuLCBIdHRwSW50ZXJjZXB0b3JGbiwgSHR0cFJlcXVlc3QsIEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgTkFVVEhfQ0xJRU5UX0NPTkZJRyB9IGZyb20gJy4uL25nbW9kdWxlL3Rva2Vucyc7XG5pbXBvcnQgeyBBdXRoU2VydmljZSB9IGZyb20gJy4uL25nbW9kdWxlL2F1dGguc2VydmljZSc7XG5pbXBvcnQgeyBjcmVhdGVOQXV0aEF1dGhIdHRwSW50ZXJjZXB0b3IgfSBmcm9tICcuL2F1dGgtaW50ZXJjZXB0b3Iuc2hhcmVkJztcblxuLyoqXG4gKiBBbmd1bGFyIEhUVFAgaW50ZXJjZXB0b3IgZm9yIG5hdXRoLXRvb2xraXQuXG4gKlxuICogSGFuZGxlczpcbiAqIC0gQ29va2llcyBtb2RlOiB3aXRoQ3JlZGVudGlhbHMgKyBDU1JGIHRva2VucyArIHJlZnJlc2ggdmlhIFBPU1RcbiAqIC0gSlNPTiBtb2RlOiByZWZyZXNoIHZpYSBTREssIHJldHJ5IHdpdGggbmV3IHRva2VuXG4gKi9cbmV4cG9ydCBjb25zdCBhdXRoSW50ZXJjZXB0b3I6IEh0dHBJbnRlcmNlcHRvckZuID0gKHJlcTogSHR0cFJlcXVlc3Q8dW5rbm93bj4sIG5leHQ6IEh0dHBIYW5kbGVyRm4pID0+IHtcbiAgY29uc3QgY29uZmlnID0gaW5qZWN0KE5BVVRIX0NMSUVOVF9DT05GSUcpO1xuICBjb25zdCBodHRwID0gaW5qZWN0KEh0dHBDbGllbnQpO1xuICBjb25zdCBhdXRoU2VydmljZSA9IGluamVjdChBdXRoU2VydmljZSk7XG4gIGNvbnN0IHBsYXRmb3JtSWQgPSBpbmplY3QoUExBVEZPUk1fSUQpO1xuICBjb25zdCByb3V0ZXIgPSBpbmplY3QoUm91dGVyKTtcbiAgY29uc3QgaXNCcm93c2VyID0gaXNQbGF0Zm9ybUJyb3dzZXIocGxhdGZvcm1JZCk7XG5cbiAgaWYgKCFpc0Jyb3dzZXIpIHtcbiAgICByZXR1cm4gbmV4dChyZXEpO1xuICB9XG5cbiAgcmV0dXJuIGNyZWF0ZU5BdXRoQXV0aEh0dHBJbnRlcmNlcHRvcih7IGNvbmZpZywgaHR0cCwgYXV0aFNlcnZpY2UsIHJvdXRlciwgbmV4dCwgcmVxIH0pO1xufTtcblxuLyoqXG4gKiBDbGFzcy1iYXNlZCBpbnRlcmNlcHRvciBmb3IgTmdNb2R1bGUgY29tcGF0aWJpbGl0eS5cbiAqL1xuZXhwb3J0IGNsYXNzIEF1dGhJbnRlcmNlcHRvciB7XG4gIGludGVyY2VwdChyZXE6IEh0dHBSZXF1ZXN0PHVua25vd24+LCBuZXh0OiBIdHRwSGFuZGxlckZuKSB7XG4gICAgcmV0dXJuIGF1dGhJbnRlcmNlcHRvcihyZXEsIG5leHQpO1xuICB9XG59XG4iXX0=