@nauth-toolkit/client-angular 0.1.60 → 0.1.62
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.
|
@@ -41,6 +41,22 @@ export const authInterceptor = (req, next) => {
|
|
|
41
41
|
if (!isBrowser) {
|
|
42
42
|
return next(req);
|
|
43
43
|
}
|
|
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
|
|
44
60
|
const tokenDelivery = config.tokenDelivery;
|
|
45
61
|
const baseUrl = config.baseUrl;
|
|
46
62
|
const endpoints = config.endpoints ?? {};
|
|
@@ -75,6 +91,8 @@ export const authInterceptor = (req, next) => {
|
|
|
75
91
|
if (!shouldHandle) {
|
|
76
92
|
return throwError(() => error);
|
|
77
93
|
}
|
|
94
|
+
// Mark original request as retried to prevent infinite loops
|
|
95
|
+
retriedRequests.add(req);
|
|
78
96
|
if (config.debug) {
|
|
79
97
|
console.warn('[nauth-interceptor] 401 detected:', req.url);
|
|
80
98
|
}
|
|
@@ -96,20 +114,70 @@ export const authInterceptor = (req, next) => {
|
|
|
96
114
|
// Get new token (JSON mode) or signal success (cookies mode)
|
|
97
115
|
const newToken = 'accessToken' in response ? response.accessToken : 'success';
|
|
98
116
|
refreshTokenSubject.next(newToken ?? 'success');
|
|
99
|
-
//
|
|
100
|
-
|
|
101
|
-
|
|
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
|
|
102
158
|
if (config.debug) {
|
|
103
159
|
console.warn('[nauth-interceptor] Retrying:', req.url);
|
|
104
160
|
}
|
|
105
|
-
|
|
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
|
+
}));
|
|
106
172
|
}), catchError((err) => {
|
|
173
|
+
// This only catches REFRESH failures, not retry failures
|
|
107
174
|
if (config.debug) {
|
|
108
175
|
console.error('[nauth-interceptor] Refresh failed:', err);
|
|
109
176
|
}
|
|
110
177
|
isRefreshing = false;
|
|
111
178
|
refreshTokenSubject.next(null);
|
|
112
179
|
// Handle session expiration - redirect to configured URL
|
|
180
|
+
// Only redirect if refresh itself failed (not if retry failed)
|
|
113
181
|
if (config.redirects?.sessionExpired) {
|
|
114
182
|
router.navigateByUrl(config.redirects.sessionExpired).catch((navError) => {
|
|
115
183
|
if (config.debug) {
|
|
@@ -129,23 +197,91 @@ export const authInterceptor = (req, next) => {
|
|
|
129
197
|
if (config.debug) {
|
|
130
198
|
console.warn('[nauth-interceptor] Refresh done, retrying:', req.url);
|
|
131
199
|
}
|
|
132
|
-
const retryReq = buildRetryRequest(authReq, tokenDelivery, token);
|
|
133
|
-
|
|
134
|
-
|
|
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
|
+
}));
|
|
135
209
|
}));
|
|
136
210
|
}
|
|
137
211
|
}));
|
|
138
212
|
};
|
|
139
213
|
/**
|
|
140
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
|
|
141
227
|
*/
|
|
142
|
-
function buildRetryRequest(originalReq, tokenDelivery, newToken) {
|
|
228
|
+
function buildRetryRequest(originalReq, tokenDelivery, newToken, csrfConfig) {
|
|
143
229
|
if (tokenDelivery === 'json' && newToken && newToken !== 'success') {
|
|
144
230
|
return originalReq.clone({
|
|
145
231
|
setHeaders: { Authorization: `Bearer ${newToken}` },
|
|
146
232
|
});
|
|
147
233
|
}
|
|
148
|
-
|
|
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;
|
|
149
285
|
}
|
|
150
286
|
/**
|
|
151
287
|
* Class-based interceptor for NgModule compatibility.
|
|
@@ -155,4 +291,4 @@ export class AuthInterceptor {
|
|
|
155
291
|
return authInterceptor(req, next);
|
|
156
292
|
}
|
|
157
293
|
}
|
|
158
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5pbnRlcmNlcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvYXV0aC5pbnRlcmNlcHRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNwRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNwRCxPQUFPLEVBQWlELFVBQVUsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3BILE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzlGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUV2RDs7O0dBR0c7QUFDSCxJQUFJLFlBQVksR0FBRyxLQUFLLENBQUM7QUFDekIsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLGVBQWUsQ0FBZ0IsSUFBSSxDQUFDLENBQUM7QUFFckU7O0dBRUc7QUFDSCxNQUFNLGVBQWUsR0FBRyxJQUFJLE9BQU8sRUFBd0IsQ0FBQztBQUU1RDs7R0FFRztBQUNILFNBQVMsWUFBWSxDQUFDLFVBQWtCO0lBQ3RDLElBQUksT0FBTyxRQUFRLEtBQUssV0FBVztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ2pELE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLFFBQVEsVUFBVSxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQzlFLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENB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LFFBQVEsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNuRSxPQUFPLFdBQVcsQ0FBQyxLQUFLLENBQUM7WUFDdkIsVUFBVSxFQUFFLEVBQUUsYUFBYSxFQUFFLFVBQVUsUUFBUSxFQUFFLEVBQUU7U0FDcEQsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUNELE9BQU8sV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQzdCLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sT0FBTyxlQUFlO0lBQzFCLFNBQVMsQ0FBQyxHQUF5QixFQUFFLElBQW1CO1FBQ3RELE9BQU8sZUFBZSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNwQyxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbmplY3QsIFBMQVRGT1JNX0lEIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBIdHRwSGFuZGxlckZuLCBIdHRwSW50ZXJjZXB0b3JGbiwgSHR0cFJlcXVlc3QsIEh0dHBDbGllbnQsIEh0dHBFcnJvclJlc3BvbnNlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIHN3aXRjaE1hcCwgdGhyb3dFcnJvciwgZmlsdGVyLCB0YWtlLCBCZWhhdmlvclN1YmplY3QsIGZyb20gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IE5BVVRIX0NMSUVOVF9DT05GSUcgfSBmcm9tICcuLi9uZ21vZHVsZS90b2tlbnMnO1xuaW1wb3J0IHsgQXV0aFNlcnZpY2UgfSBmcm9tICcuLi9uZ21vZHVsZS9hdXRoLnNlcnZpY2UnO1xuXG4vKipcbiAqIFJlZnJlc2ggc3RhdGUgbWFuYWdlbWVudC5cbiAqIEJlaGF2aW9yU3ViamVjdCBwYXR0ZXJuIGlzIHRoZSBpbmR1c3RyeS1zdGFuZGFyZCBmb3IgdG9rZW4gcmVmcmVzaC5cbiAqL1xubGV0IGlzUmVmcmVzaGluZyA9IGZhbHNlO1xuY29uc3QgcmVmcmVzaFRva2VuU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8c3RyaW5nIHwgbnVsbD4obnVsbCk7XG5cbi8qKlxuICogVHJhY2sgcmV0cmllZCByZXF1ZXN0cyB0byBwcmV2ZW50IGluZmluaXRlIGxvb3BzLlxuICovXG5jb25zdCByZXRyaWVkUmVxdWVzdHMgPSBuZXcgV2Vha1NldDxIdHRwUmVxdWVzdDx1bmtub3duPj4oKTtcblxuLyoqXG4gKiBHZXQgQ1NSRiB0b2tlbiBmcm9tIGNvb2tpZS5cbiAqL1xuZnVuY3Rpb24gZ2V0Q3NyZlRva2VuKGNvb2tpZU5hbWU6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICBpZiAodHlwZW9mIGRvY3VtZW50ID09PSAndW5kZWZpbmVkJykgcmV0dXJuIG51bGw7XG4gIGNvbnN0IG1hdGNoID0gZG9jdW1lbnQuY29va2llLm1hdGNoKG5ldyBSZWdFeHAoYChefCApJHtjb29raWVOYW1lfT0oW147XSspYCkpO1xuICByZXR1cm4gbWF0Y2ggPyBkZWNvZGVVUklDb21wb25lbnQobWF0Y2hbMl0pIDogbnVsbDtcbn1cblxuLyoqXG4gKiBBbmd1bGFyIEhUVFAgaW50ZXJjZXB0b3IgZm9yIG5hdXRoLXRvb2xraXQuXG4gKlxuICogSGFuZGxlczpcbiAqIC0gQ29va2llcyBtb2RlOiB3aXRoQ3JlZGVudGlhbHMgKyBDU1JGIHRva2VucyArIHJlZnJlc2ggdmlhIFBPU1RcbiAqIC0gSlNPTiBtb2RlOiByZWZyZXNoIHZpYSBTREssIHJldHJ5IHdpdGggbmV3IHRva2VuXG4gKi9cbmV4cG9ydCBjb25zdCBhdXRoSW50ZXJjZXB0b3I6IEh0dHBJbnRlcmNlcHRvckZuID0gKHJlcTogSHR0cFJlcXVlc3Q8dW5rbm93bj4sIG5leHQ6IEh0dHBIYW5kbGVyRm4pID0+IHtcbiAgY29uc3QgY29uZmlnID0gaW5qZWN0KE5BVVRIX0NMSUVOVF9DT05GSUcpO1xuICBjb25zdCBodHRwID0gaW5qZWN0KEh0dHBDbGllbnQpO1xuICBjb25zdCBhdXRoU2VydmljZSA9IGluamVjdChBdXRoU2VydmljZSk7XG4gIGNvbnN0IHBsYXRmb3JtSWQgPSBpbmplY3QoUExBVEZPUk1fSUQpO1xuICBjb25zdCByb3V0ZXIgPSBpbmplY3QoUm91dGVyKTtcbiAgY29uc3QgaXNCcm93c2VyID0gaXNQbGF0Zm9ybUJyb3dzZXIocGxhdGZvcm1JZCk7XG5cbiAgaWYgKCFpc0Jyb3dzZXIpIHtcbiAgICByZXR1cm4gbmV4dChyZXEpO1xuICB9XG5cbiAgY29uc3QgdG9rZW5EZWxpdmVyeSA9IGNvbmZpZy50b2tlbkRlbGl2ZXJ5O1xuICBjb25zdCBiYXNlVXJsID0gY29uZmlnLmJhc2VVcmw7XG4gIGNvbnN0IGVuZHBvaW50cyA9IGNvbmZpZy5lbmRwb2ludHMgPz8ge307XG4gIGNvbnN0IHJlZnJlc2hQYXRoID0gZW5kcG9pbnRzLnJlZnJlc2ggPz8gJy9yZWZyZXNoJztcbiAgY29uc3QgbG9naW5QYXRoID0gZW5kcG9pbnRzLmxvZ2luID8/ICcvbG9naW4nO1xuICBjb25zdCBzaWdudXBQYXRoID0gZW5kcG9pbnRzLnNpZ251cCA/PyAnL3NpZ251cCc7XG4gIGNvbnN0IHNvY2lhbEV4Y2hhbmdlUGF0aCA9IGVuZHBvaW50cy5zb2NpYWxFeGNoYW5nZSA/PyAnL3NvY2lhbC9leGNoYW5nZSc7XG4gIGNvbnN0IHJlZnJlc2hVcmwgPSBgJHtiYXNlVXJsfSR7cmVmcmVzaFBhdGh9YDtcblxuICBjb25zdCBpc0F1dGhBcGlSZXF1ZXN0ID0gcmVxLnVybC5pbmNsdWRlcyhiYXNlVXJsKTtcbiAgY29uc3QgaXNSZWZyZXNoRW5kcG9pbnQgPSByZXEudXJsLmluY2x1ZGVzKHJlZnJlc2hQYXRoKTtcbiAgY29uc3QgaXNQdWJsaWNFbmRwb2ludCA9XG4gICAgcmVxLnVybC5pbmNsdWRlcyhsb2dpblBhdGgpIHx8IHJlcS51cmwuaW5jbHVkZXMoc2lnbnVwUGF0aCkgfHwgcmVxLnVybC5pbmNsdWRlcyhzb2NpYWxFeGNoYW5nZVBhdGgpO1xuXG4gIC8vIEJ1aWxkIHJlcXVlc3Qgd2l0aCBjcmVkZW50aWFscyAoY29va2llcyBtb2RlIG9ubHkpXG4gIGxldCBhdXRoUmVxID0gcmVxO1xuICBpZiAodG9rZW5EZWxpdmVyeSA9PT0gJ2Nvb2tpZXMnKSB7XG4gICAgYXV0aFJlcSA9IGF1dGhSZXEuY2xvbmUoeyB3aXRoQ3JlZGVudGlhbHM6IHRydWUgfSk7XG5cbiAgICBpZiAoWydQT1NUJywgJ1BVVCcsICdQQVRDSCcsICdERUxFVEUnXS5pbmNsdWRlcyhyZXEubWV0aG9kKSkge1xuICAgICAgY29uc3QgY3NyZkNvb2tpZU5hbWUgPSBjb25maWcuY3NyZj8uY29va2llTmFtZSA/PyAnbmF1dGhfY3NyZl90b2tlbic7XG4gICAgICBjb25zdCBjc3JmSGVhZGVyTmFtZSA9IGNvbmZpZy5jc3JmPy5oZWFkZXJOYW1lID8/ICd4LWNzcmYtdG9rZW4nO1xuICAgICAgY29uc3QgY3NyZlRva2VuID0gZ2V0Q3NyZlRva2VuKGNzcmZDb29raWVOYW1lKTtcbiAgICAgIGlmIChjc3JmVG9rZW4pIHtcbiAgICAgICAgYXV0aFJlcSA9IGF1dGhSZXEuY2xvbmUoeyBzZXRIZWFkZXJzOiB7IFtjc3JmSGVhZGVyTmFtZV06IGNzcmZUb2tlbiB9IH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXh0KGF1dGhSZXEpLnBpcGUoXG4gICAgY2F0Y2hFcnJvcigoZXJyb3I6IHVua25vd24pID0+IHtcbiAgICAgIGNvbnN0IHNob3VsZEhhbmRsZSA9XG4gICAgICAgIGVycm9yIGluc3RhbmNlb2YgSHR0cEVycm9yUmVzcG9uc2UgJiZcbiAgICAgICAgZXJyb3Iuc3RhdHVzID09PSA0MDEgJiZcbiAgICAgICAgaXNBdXRoQXBpUmVxdWVzdCAmJlxuICAgICAgICAhaXNSZWZyZXNoRW5kcG9pbnQgJiZcbiAgICAgICAgIWlzUHVibGljRW5kcG9pbnQgJiZcbiAgICAgICAgIXJldHJpZWRSZXF1ZXN0cy5oYXMocmVxKTtcblxuICAgICAgaWYgKCFzaG91bGRIYW5kbGUpIHtcbiAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gZXJyb3IpO1xuICAgICAgfVxuXG4gICAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignW25hdXRoLWludGVyY2VwdG9yXSA0MDEgZGV0ZWN0ZWQ6JywgcmVxLnVybCk7XG4gICAgICB9XG5cbiAgICAgIGlmICghaXNSZWZyZXNoaW5nKSB7XG4gICAgICAgIGlzUmVmcmVzaGluZyA9IHRydWU7XG4gICAgICAgIHJlZnJlc2hUb2tlblN1YmplY3QubmV4dChudWxsKTtcblxuICAgICAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICAgICAgY29uc29sZS53YXJuKCdbbmF1dGgtaW50ZXJjZXB0b3JdIFN0YXJ0aW5nIHJlZnJlc2guLi4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlZnJlc2ggYmFzZWQgb24gbW9kZVxuICAgICAgICBjb25zdCByZWZyZXNoJCA9XG4gICAgICAgICAgdG9rZW5EZWxpdmVyeSA9PT0gJ2Nvb2tpZXMnXG4gICAgICAgICAgICA/IGh0dHAucG9zdDx7IGFjY2Vzc1Rva2VuPzogc3RyaW5nIH0+KHJlZnJlc2hVcmwsIHt9LCB7IHdpdGhDcmVkZW50aWFsczogdHJ1ZSB9KVxuICAgICAgICAgICAgOiBmcm9tKGF1dGhTZXJ2aWNlLnJlZnJlc2goKSk7XG5cbiAgICAgICAgcmV0dXJuIHJlZnJlc2gkLnBpcGUoXG4gICAgICAgICAgc3dpdGNoTWFwKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tuYXV0aC1pbnRlcmNlcHRvcl0gUmVmcmVzaCBzdWNjZXNzZnVsJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpc1JlZnJlc2hpbmcgPSBmYWxzZTtcblxuICAgICAgICAgICAgLy8gR2V0IG5ldyB0b2tlbiAoSlNPTiBtb2RlKSBvciBzaWduYWwgc3VjY2VzcyAoY29va2llcyBtb2RlKVxuICAgICAgICAgICAgY29uc3QgbmV3VG9rZW4gPSAnYWNjZXNzVG9rZW4nIGluIHJlc3BvbnNlID8gcmVzcG9uc2UuYWNjZXNzVG9rZW4gOiAnc3VjY2Vzcyc7XG4gICAgICAgICAgICByZWZyZXNoVG9rZW5TdWJqZWN0Lm5leHQobmV3VG9rZW4gPz8gJ3N1Y2Nlc3MnKTtcblxuICAgICAgICAgICAgLy8gQnVpbGQgcmV0cnkgcmVxdWVzdFxuICAgICAgICAgICAgY29uc3QgcmV0cnlSZXEgPSBidWlsZFJldHJ5UmVxdWVzdChhdXRoUmVxLCB0b2tlbkRlbGl2ZXJ5LCBuZXdUb2tlbik7XG4gICAgICAgICAgICByZXRyaWVkUmVxdWVzdHMuYWRkKHJldHJ5UmVxKTtcblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tuYXV0aC1pbnRlcmNlcHRvcl0gUmV0cnlpbmc6JywgcmVxLnVybCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV4dChyZXRyeVJlcSk7XG4gICAgICAgICAgfSksXG4gICAgICAgICAgY2F0Y2hFcnJvcigoZXJyKSA9PiB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1tuYXV0aC1pbnRlcmNlcHRvcl0gUmVmcmVzaCBmYWlsZWQ6JywgZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlzUmVmcmVzaGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmVmcmVzaFRva2VuU3ViamVjdC5uZXh0KG51bGwpO1xuXG4gICAgICAgICAgICAvLyBIYW5kbGUgc2Vzc2lvbiBleHBpcmF0aW9uIC0gcmVkaXJlY3QgdG8gY29uZmlndXJlZCBVUkxcbiAgICAgICAgICAgIGlmIChjb25maWcucmVkaXJlY3RzPy5zZXNzaW9uRXhwaXJlZCkge1xuICAgICAgICAgICAgICByb3V0ZXIubmF2aWdhdGVCeVVybChjb25maWcucmVkaXJlY3RzLnNlc3Npb25FeHBpcmVkKS5jYXRjaCgobmF2RXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdbbmF1dGgtaW50ZXJjZXB0b3JdIE5hdmlnYXRpb24gZmFpbGVkOicsIG5hdkVycm9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnIpO1xuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gV2FpdCBmb3Igb25nb2luZyByZWZyZXNoXG4gICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJ1tuYXV0aC1pbnRlcmNlcHRvcl0gV2FpdGluZyBmb3IgcmVmcmVzaC4uLicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZWZyZXNoVG9rZW5TdWJqZWN0LnBpcGUoXG4gICAgICAgICAgZmlsdGVyKCh0b2tlbik6IHRva2VuIGlzIHN0cmluZyA9PiB0b2tlbiAhPT0gbnVsbCksXG4gICAgICAgICAgdGFrZSgxKSxcbiAgICAgICAgICBzd2l0Y2hNYXAoKHRva2VuKSA9PiB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUud2FybignW25hdXRoLWludGVyY2VwdG9yXSBSZWZyZXNoIGRvbmUsIHJldHJ5aW5nOicsIHJlcS51cmwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmV0cnlSZXEgPSBidWlsZFJldHJ5UmVxdWVzdChhdXRoUmVxLCB0b2tlbkRlbGl2ZXJ5LCB0b2tlbik7XG4gICAgICAgICAgICByZXRyaWVkUmVxdWVzdHMuYWRkKHJldHJ5UmVxKTtcbiAgICAgICAgICAgIHJldHVybiBuZXh0KHJldHJ5UmVxKTtcbiAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KSxcbiAgKTtcbn07XG5cbi8qKlxuICogQnVpbGQgcmV0cnkgcmVxdWVzdCB3aXRoIGFwcHJvcHJpYXRlIGF1dGguXG4gKi9cbmZ1bmN0aW9uIGJ1aWxkUmV0cnlSZXF1ZXN0KFxuICBvcmlnaW5hbFJlcTogSHR0cFJlcXVlc3Q8dW5rbm93bj4sXG4gIHRva2VuRGVsaXZlcnk6IHN0cmluZyxcbiAgbmV3VG9rZW4/OiBzdHJpbmcsXG4pOiBIdHRwUmVxdWVzdDx1bmtub3duPiB7XG4gIGlmICh0b2tlbkRlbGl2ZXJ5ID09PSAnanNvbicgJiYgbmV3VG9rZW4gJiYgbmV3VG9rZW4gIT09ICdzdWNjZXNzJykge1xuICAgIHJldHVybiBvcmlnaW5hbFJlcS5jbG9uZSh7XG4gICAgICBzZXRIZWFkZXJzOiB7IEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHtuZXdUb2tlbn1gIH0sXG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIG9yaWdpbmFsUmVxLmNsb25lKCk7XG59XG5cbi8qKlxuICogQ2xhc3MtYmFzZWQgaW50ZXJjZXB0b3IgZm9yIE5nTW9kdWxlIGNvbXBhdGliaWxpdHkuXG4gKi9cbmV4cG9ydCBjbGFzcyBBdXRoSW50ZXJjZXB0b3Ige1xuICBpbnRlcmNlcHQocmVxOiBIdHRwUmVxdWVzdDx1bmtub3duPiwgbmV4dDogSHR0cEhhbmRsZXJGbikge1xuICAgIHJldHVybiBhdXRoSW50ZXJjZXB0b3IocmVxLCBuZXh0KTtcbiAgfVxufVxuIl19
|
|
294
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5pbnRlcmNlcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvYXV0aC5pbnRlcmNlcHRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNwRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNwRCxPQUFPLEVBQWlELFVBQVUsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3BILE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzlGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUV2RDs7O0dBR0c7QUFDSCxJQUFJLFlBQVksR0FBRyxLQUFLLENBQUM7QUFDekIsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLGVBQWUsQ0FBZ0IsSUFBSSxDQUFDLENBQUM7QUFFckU7O0dBRUc7QUFDSCxNQUFNLGVBQWUsR0FBRyxJQUFJLE9BQU8sRUFBd0IsQ0FBQztBQUU1RDs7R0FFRztBQUNILFNBQVMsWUFBWSxDQUFDLFVBQWtCO0lBQ3RDLElBQUksT0FBTyxRQUFRLEtBQUssV0FBVztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ2pELE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLFFBQVEsVUFBVSxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQzlFLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0FBQ3JELENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQXNCLENBQUMsR0FBeUIsRUFBRSxJQUFtQixFQUFFLEVBQUU7SUFDbkcsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDM0MsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ2hDLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUN4QyxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDdkMsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzlCLE1BQU0sU0FBUyxHQUFHLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBRWhELElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNmLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ25CLENBQUM7SUFFRCxvQkFBb0I7SUFDcEIsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLEtBQUssRUFBRSxDQUFDO1FBQ3pELEtBQUssQ0FBQyxtRUFBbUUsRUFBRTtZQUN6RSxNQUFNLEVBQUUsTUFBTTtZQUNkLE9BQU8sRUFBRSxFQUFFLGNBQWMsRUFBRSxrQkFBa0IsRUFBRTtZQUMvQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQztnQkFDbkIsUUFBUSxFQUFFLDJCQUEyQjtnQkFDckMsT0FBTyxFQUFFLHdCQUF3QjtnQkFDakMsSUFBSSxFQUFFLEVBQUUsT0FBTyxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUFFLE9BQU8sR0FBRyxDQUFDLElBQUksRUFBRSxTQUFTLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQUcsRUFBRTtnQkFDakcsU0FBUyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7Z0JBQ3JCLFNBQVMsRUFBRSxlQUFlO2dCQUMxQixZQUFZLEVBQUUsR0FBRzthQUNsQixDQUFDO1NBQ0gsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUMsQ0FBQztJQUNyQixDQUFDO0lBQ0QsYUFBYTtJQUViLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUM7SUFDM0MsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQztJQUMvQixNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsU0FBUyxJQUFJLEVBQUUsQ0FBQztJQUN6QyxNQUFNLFdBQVcsR0FBRyxTQUFTLENBQUMsT0FBTyxJQUFJLFVBQVUsQ0FBQztJQUNwRCxNQUFNLFNBQVMsR0FBRyxTQUFTLENBQUMsS0FBSyxJQUFJLFFBQVEsQ0FBQztJQUM5QyxNQUFNLFVBQVUsR0FBRyxTQUFTLENBQUMsTUFBTSxJQUFJLFNBQVMsQ0FBQztJQUNqRCxNQUFNLGtCQUFrQixHQUFHLFNBQVMsQ0FBQyxjQUFjLElBQUksa0JBQWtCLENBQUM7SUFDMUUsTUFBTSxVQUFVLEdBQUcsR0FBRyxPQUFPLEdBQUcsV0FBVyxFQUFFLENBQUM7SUFFOUMsTUFBTSxnQkFBZ0IsR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNuRCxNQUFNLGlCQUFpQixHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3hELE1BQU0sZ0JBQWdCLEdBQ3BCLEdBQUcsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLGtCQUFrQixDQUFDLENBQUM7SUFFdEcscURBQXFEO0lBQ3JELElBQUksT0FBTyxHQUFHLEdBQUcsQ0FBQztJQUNsQixJQUFJLGFBQWEsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNoQyxPQUFPLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBRW5ELElBQUksQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDNUQsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLElBQUksRUFBRSxVQUFVLElBQUksa0JBQWtCLENBQUM7WUFDckUsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLElBQUksRUFBRSxVQUFVLElBQUksY0FBYyxDQUFDO1lBQ2pFLE1BQU0sU0FBUyxHQUFHLFlBQVksQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUMvQyxJQUFJLFNBQVMsRUFBRSxDQUFDO2dCQUNkLE9BQU8sR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsVUFBVSxFQUFFLEVBQUUsQ0FBQyxjQUFjLENBQUMsRUFBRSxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDM0UsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUN2QixVQUFVLENBQUMsQ0FBQyxLQUFjLEVBQUUsRUFBRTtRQUM1QixNQUFNLFlBQVksR0FDaEIsS0FBSyxZQUFZLGlCQUFpQjtZQUNsQyxLQUFLLENBQUMsTUFBTSxLQUFLLEdBQUc7WUFDcEIsZ0JBQWdCO1lBQ2hCLENBQUMsaUJBQWlCO1lBQ2xCLENBQUMsZ0JBQWdCO1lBQ2pCLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUU1QixJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDbEIsT0FBTyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDakMsQ0FBQztRQUVELDZEQUE2RDtRQUM3RCxlQUFlLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRXpCLElBQUksTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2pCLE9BQU8sQ0FBQyxJQUFJLENBQUMsbUNBQW1DLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzdELENBQUM7UUFFRCxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDbEIsWUFBWSxHQUFHLElBQUksQ0FBQztZQUNwQixtQkFBbUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFFL0IsSUFBSSxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ2pCLE9BQU8sQ0FBQyxJQUFJLENBQUMseUNBQXlDLENBQUMsQ0FBQztZQUMxRCxDQUFDO1lBRUQsd0JBQXdCO1lBQ3hCLE1BQU0sUUFBUSxHQUNaLGFBQWEsS0FBSyxTQUFTO2dCQUN6QixDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBMkIsVUFBVSxFQUFFLEVBQUUsRUFBRSxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUsQ0FBQztnQkFDaEYsQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUVsQyxPQUFPLFFBQVEsQ0FBQyxJQUFJLENBQ2xCLFNBQVMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFO2dCQUNyQixJQUFJLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztvQkFDakIsT0FBTyxDQUFDLElBQUksQ0FBQyx3Q0FBd0MsQ0FBQyxDQUFDO2dCQUN6RCxDQUFDO2dCQUNELFlBQVksR0FBRyxLQUFLLENBQUM7Z0JBRXJCLDZEQUE2RDtnQkFDN0QsTUFBTSxRQUFRLEdBQUcsYUFBYSxJQUFJLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO2dCQUM5RSxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsUUFBUSxJQUFJLFNBQVMsQ0FBQyxDQUFDO2dCQUVoRCxvQkFBb0I7Z0JBQ3BCLEtBQUssQ0FBQyxtRUFBbUUsRUFBRTtvQkFDekUsTUFBTSxFQUFFLE1BQU07b0JBQ2QsT0FBTyxFQUFFLEVBQUUsY0FBYyxFQUFFLGtCQUFrQixFQUFFO29CQUMvQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQzt3QkFDbkIsUUFBUSxFQUFFLHlCQUF5Qjt3QkFDbkMsT0FBTyxFQUFFLDBCQUEwQjt3QkFDbkMsSUFBSSxFQUFFOzRCQUNKLFdBQVcsRUFBRSxPQUFPLENBQUMsSUFBSTs0QkFDekIsYUFBYSxFQUFFLE9BQU8sQ0FBQyxNQUFNOzRCQUM3QixVQUFVLEVBQUUsT0FBTyxDQUFDLEdBQUc7NEJBQ3ZCLGVBQWUsRUFBRSxPQUFPLE9BQU8sQ0FBQyxJQUFJO3lCQUNyQzt3QkFDRCxTQUFTLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTt3QkFDckIsU0FBUyxFQUFFLGVBQWU7d0JBQzFCLFlBQVksRUFBRSxHQUFHO3FCQUNsQixDQUFDO2lCQUNILENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQ25CLGFBQWE7Z0JBRWIsZ0ZBQWdGO2dCQUNoRixNQUFNLFFBQVEsR0FBRyxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUsYUFBYSxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBRWxGLG9CQUFvQjtnQkFDcEIsS0FBSyxDQUFDLG1FQUFtRSxFQUFFO29CQUN6RSxNQUFNLEVBQUUsTUFBTTtvQkFDZCxPQUFPLEVBQUUsRUFBRSxjQUFjLEVBQUUsa0JBQWtCLEVBQUU7b0JBQy9DLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDO3dCQUNuQixRQUFRLEVBQUUseUJBQXlCO3dCQUNuQyxPQUFPLEVBQUUseUJBQXlCO3dCQUNsQyxJQUFJLEVBQUU7NEJBQ0osWUFBWSxFQUFFLFFBQVEsQ0FBQyxJQUFJOzRCQUMzQixjQUFjLEVBQUUsUUFBUSxDQUFDLE1BQU07NEJBQy9CLFdBQVcsRUFBRSxRQUFRLENBQUMsR0FBRzs0QkFDekIsZ0JBQWdCLEVBQUUsT0FBTyxRQUFRLENBQUMsSUFBSTs0QkFDdEMsV0FBVyxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFO3lCQUNyQzt3QkFDRCxTQUFTLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTt3QkFDckIsU0FBUyxFQUFFLGVBQWU7d0JBQzFCLFlBQVksRUFBRSxHQUFHO3FCQUNsQixDQUFDO2lCQUNILENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQ25CLGFBQWE7Z0JBRWIsSUFBSSxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7b0JBQ2pCLE9BQU8sQ0FBQyxJQUFJLENBQUMsK0JBQStCLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUN6RCxDQUFDO2dCQUVELDBDQUEwQztnQkFDMUMsNkVBQTZFO2dCQUM3RSx5RUFBeUU7Z0JBQ3pFLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksQ0FDeEIsVUFBVSxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7b0JBQ3RCLDhDQUE4QztvQkFDOUMscURBQXFEO29CQUNyRCxJQUFJLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQzt3QkFDakIsT0FBTyxDQUFDLElBQUksQ0FBQywyQ0FBMkMsRUFBRSxRQUFRLENBQUMsQ0FBQztvQkFDdEUsQ0FBQztvQkFDRCxPQUFPLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDcEMsQ0FBQyxDQUFDLENBQ0gsQ0FBQztZQUNKLENBQUMsQ0FBQyxFQUNGLFVBQVUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO2dCQUNqQix5REFBeUQ7Z0JBQ3pELElBQUksTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO29CQUNqQixPQUFPLENBQUMsS0FBSyxDQUFDLHFDQUFxQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO2dCQUM1RCxDQUFDO2dCQUNELFlBQVksR0FBRyxLQUFLLENBQUM7Z0JBQ3JCLG1CQUFtQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFFL0IseURBQXlEO2dCQUN6RCwrREFBK0Q7Z0JBQy9ELElBQUksTUFBTSxDQUFDLFNBQVMsRUFBRSxjQUFjLEVBQUUsQ0FBQztvQkFDckMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFO3dCQUN2RSxJQUFJLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQzs0QkFDakIsT0FBTyxDQUFDLEtBQUssQ0FBQyx3Q0FBd0MsRUFBRSxRQUFRLENBQUMsQ0FBQzt3QkFDcEUsQ0FBQztvQkFDSCxDQUFDLENBQUMsQ0FBQztnQkFDTCxDQUFDO2dCQUVELE9BQU8sVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQy9CLENBQUMsQ0FBQyxDQUNILENBQUM7UUFDSixDQUFDO2FBQU0sQ0FBQztZQUNOLDJCQUEyQjtZQUMzQixJQUFJLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDakIsT0FBTyxDQUFDLElBQUksQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFDO1lBQzdELENBQUM7WUFDRCxPQUFPLG1CQUFtQixDQUFDLElBQUksQ0FDN0IsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFtQixFQUFFLENBQUMsS0FBSyxLQUFLLElBQUksQ0FBQyxFQUNsRCxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQ1AsU0FBUyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7Z0JBQ2xCLElBQUksTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO29CQUNqQixPQUFPLENBQUMsSUFBSSxDQUFDLDZDQUE2QyxFQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDdkUsQ0FBQztnQkFDRCxNQUFNLFFBQVEsR0FBRyxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBRS9FLDREQUE0RDtnQkFDNUQsaURBQWlEO2dCQUNqRCxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQ3hCLFVBQVUsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFO29CQUN0QixJQUFJLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQzt3QkFDakIsT0FBTyxDQUFDLElBQUksQ0FBQywyQ0FBMkMsRUFBRSxRQUFRLENBQUMsQ0FBQztvQkFDdEUsQ0FBQztvQkFDRCxPQUFPLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDcEMsQ0FBQyxDQUFDLENBQ0gsQ0FBQztZQUNKLENBQUMsQ0FBQyxDQUNILENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQ0gsQ0FBQztBQUNKLENBQUMsQ0FBQztBQUVGOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBQ0gsU0FBUyxpQkFBaUIsQ0FDeEIsV0FBaUMsRUFDakMsYUFBcUIsRUFDckIsUUFBaUIsRUFDakIsVUFBeUQ7SUFFekQsSUFBSSxhQUFhLEtBQUssTUFBTSxJQUFJLFFBQVEsSUFBSSxRQUFRLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDbkUsT0FBTyxXQUFXLENBQUMsS0FBSyxDQUFDO1lBQ3ZCLFVBQVUsRUFBRSxFQUFFLGFBQWEsRUFBRSxVQUFVLFFBQVEsRUFBRSxFQUFFO1NBQ3BELENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCw4RkFBOEY7SUFDOUYsMEVBQTBFO0lBQzFFLDhFQUE4RTtJQUM5RSw4RUFBOEU7SUFDOUUsSUFBSSxhQUFhLEtBQUssU0FBUyxJQUFJLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQ25HLE1BQU0sY0FBYyxHQUFHLFVBQVUsRUFBRSxVQUFVLElBQUksa0JBQWtCLENBQUM7UUFDcEUsTUFBTSxjQUFjLEdBQUcsVUFBVSxFQUFFLFVBQVUsSUFBSSxjQUFjLENBQUM7UUFDaEUsTUFBTSxjQUFjLEdBQUcsWUFBWSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBRXBELG9CQUFvQjtRQUNwQixLQUFLLENBQUMsbUVBQW1FLEVBQUU7WUFDekUsTUFBTSxFQUFFLE1BQU07WUFDZCxPQUFPLEVBQUUsRUFBRSxjQUFjLEVBQUUsa0JBQWtCLEVBQUU7WUFDL0MsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUM7Z0JBQ25CLFFBQVEsRUFBRSx1Q0FBdUM7Z0JBQ2pELE9BQU8sRUFBRSx5Q0FBeUM7Z0JBQ2xELElBQUksRUFBRTtvQkFDSixlQUFlLEVBQUUsV0FBVyxDQUFDLElBQUk7b0JBQ2pDLG1CQUFtQixFQUFFLE9BQU8sV0FBVyxDQUFDLElBQUk7b0JBQzVDLGNBQWMsRUFBRSxjQUFjLEVBQUUsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7b0JBQy9DLE1BQU0sRUFBRSxXQUFXLENBQUMsTUFBTTtpQkFDM0I7Z0JBQ0QsU0FBUyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7Z0JBQ3JCLFNBQVMsRUFBRSxlQUFlO2dCQUMxQixZQUFZLEVBQUUsR0FBRzthQUNsQixDQUFDO1NBQ0gsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUMsQ0FBQztRQUNuQixhQUFhO1FBRWIsSUFBSSxjQUFjLEVBQUUsQ0FBQztZQUNuQix3Q0FBd0M7WUFDeEMsTUFBTSxNQUFNLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FBQztnQkFDL0IsVUFBVSxFQUFFLEVBQUUsQ0FBQyxjQUFjLENBQUMsRUFBRSxjQUFjLEVBQUU7YUFDakQsQ0FBQyxDQUFDO1lBRUgsb0JBQW9CO1lBQ3BCLEtBQUssQ0FBQyxtRUFBbUUsRUFBRTtnQkFDekUsTUFBTSxFQUFFLE1BQU07Z0JBQ2QsT0FBTyxFQUFFLEVBQUUsY0FBYyxFQUFFLGtCQUFrQixFQUFFO2dCQUMvQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQztvQkFDbkIsUUFBUSxFQUFFLGtEQUFrRDtvQkFDNUQsT0FBTyxFQUFFLDZCQUE2QjtvQkFDdEMsSUFBSSxFQUFFLEVBQUUsVUFBVSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsY0FBYyxFQUFFLE9BQU8sTUFBTSxDQUFDLElBQUksRUFBRSxZQUFZLEVBQUUsV0FBVyxDQUFDLElBQUksRUFBRTtvQkFDckcsU0FBUyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7b0JBQ3JCLFNBQVMsRUFBRSxlQUFlO29CQUMxQixZQUFZLEVBQUUsR0FBRztpQkFDbEIsQ0FBQzthQUNILENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDLENBQUM7WUFDbkIsYUFBYTtZQUViLE9BQU8sTUFBTSxDQUFDO1FBQ2hCLENBQUM7SUFDSCxDQUFDO0lBRUQsNkRBQTZEO0lBQzdELE9BQU8sV0FBVyxDQUFDO0FBQ3JCLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sT0FBTyxlQUFlO0lBQzFCLFNBQVMsQ0FBQyxHQUF5QixFQUFFLElBQW1CO1FBQ3RELE9BQU8sZUFBZSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNwQyxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbmplY3QsIFBMQVRGT1JNX0lEIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBIdHRwSGFuZGxlckZuLCBIdHRwSW50ZXJjZXB0b3JGbiwgSHR0cFJlcXVlc3QsIEh0dHBDbGllbnQsIEh0dHBFcnJvclJlc3BvbnNlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIHN3aXRjaE1hcCwgdGhyb3dFcnJvciwgZmlsdGVyLCB0YWtlLCBCZWhhdmlvclN1YmplY3QsIGZyb20gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IE5BVVRIX0NMSUVOVF9DT05GSUcgfSBmcm9tICcuLi9uZ21vZHVsZS90b2tlbnMnO1xuaW1wb3J0IHsgQXV0aFNlcnZpY2UgfSBmcm9tICcuLi9uZ21vZHVsZS9hdXRoLnNlcnZpY2UnO1xuXG4vKipcbiAqIFJlZnJlc2ggc3RhdGUgbWFuYWdlbWVudC5cbiAqIEJlaGF2aW9yU3ViamVjdCBwYXR0ZXJuIGlzIHRoZSBpbmR1c3RyeS1zdGFuZGFyZCBmb3IgdG9rZW4gcmVmcmVzaC5cbiAqL1xubGV0IGlzUmVmcmVzaGluZyA9IGZhbHNlO1xuY29uc3QgcmVmcmVzaFRva2VuU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8c3RyaW5nIHwgbnVsbD4obnVsbCk7XG5cbi8qKlxuICogVHJhY2sgcmV0cmllZCByZXF1ZXN0cyB0byBwcmV2ZW50IGluZmluaXRlIGxvb3BzLlxuICovXG5jb25zdCByZXRyaWVkUmVxdWVzdHMgPSBuZXcgV2Vha1NldDxIdHRwUmVxdWVzdDx1bmtub3duPj4oKTtcblxuLyoqXG4gKiBHZXQgQ1NSRiB0b2tlbiBmcm9tIGNvb2tpZS5cbiAqL1xuZnVuY3Rpb24gZ2V0Q3NyZlRva2VuKGNvb2tpZU5hbWU6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICBpZiAodHlwZW9mIGRvY3VtZW50ID09PSAndW5kZWZpbmVkJykgcmV0dXJuIG51bGw7XG4gIGNvbnN0IG1hdGNoID0gZG9jdW1lbnQuY29va2llLm1hdGNoKG5ldyBSZWdFeHAoYChefCApJHtjb29raWVOYW1lfT0oW147XSspYCkpO1xuICByZXR1cm4gbWF0Y2ggPyBkZWNvZGVVUklDb21wb25lbnQobWF0Y2hbMl0pIDogbnVsbDtcbn1cblxuLyoqXG4gKiBBbmd1bGFyIEhUVFAgaW50ZXJjZXB0b3IgZm9yIG5hdXRoLXRvb2xraXQuXG4gKlxuICogSGFuZGxlczpcbiAqIC0gQ29va2llcyBtb2RlOiB3aXRoQ3JlZGVudGlhbHMgKyBDU1JGIHRva2VucyArIHJlZnJlc2ggdmlhIFBPU1RcbiAqIC0gSlNPTiBtb2RlOiByZWZyZXNoIHZpYSBTREssIHJldHJ5IHdpdGggbmV3IHRva2VuXG4gKi9cbmV4cG9ydCBjb25zdCBhdXRoSW50ZXJjZXB0b3I6IEh0dHBJbnRlcmNlcHRvckZuID0gKHJlcTogSHR0cFJlcXVlc3Q8dW5rbm93bj4sIG5leHQ6IEh0dHBIYW5kbGVyRm4pID0+IHtcbiAgY29uc3QgY29uZmlnID0gaW5qZWN0KE5BVVRIX0NMSUVOVF9DT05GSUcpO1xuICBjb25zdCBodHRwID0gaW5qZWN0KEh0dHBDbGllbnQpO1xuICBjb25zdCBhdXRoU2VydmljZSA9IGluamVjdChBdXRoU2VydmljZSk7XG4gIGNvbnN0IHBsYXRmb3JtSWQgPSBpbmplY3QoUExBVEZPUk1fSUQpO1xuICBjb25zdCByb3V0ZXIgPSBpbmplY3QoUm91dGVyKTtcbiAgY29uc3QgaXNCcm93c2VyID0gaXNQbGF0Zm9ybUJyb3dzZXIocGxhdGZvcm1JZCk7XG5cbiAgaWYgKCFpc0Jyb3dzZXIpIHtcbiAgICByZXR1cm4gbmV4dChyZXEpO1xuICB9XG5cbiAgLy8gI3JlZ2lvbiBhZ2VudCBsb2dcbiAgaWYgKHJlcS51cmwuaW5jbHVkZXMoJy9wcm9maWxlJykgJiYgcmVxLm1ldGhvZCA9PT0gJ1BVVCcpIHtcbiAgICBmZXRjaCgnaHR0cDovLzEyNy4wLjAuMTo3MjQyL2luZ2VzdC85N2Y5ZmU1My02YThiLTQzZTItYWU5Yi00YjJkMGY3MjU4MTYnLCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9LFxuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICBsb2NhdGlvbjogJ2F1dGguaW50ZXJjZXB0b3IudHM6ZW50cnknLFxuICAgICAgICBtZXNzYWdlOiAnT3JpZ2luYWwgcmVxdWVzdCBlbnRyeScsXG4gICAgICAgIGRhdGE6IHsgcmVxQm9keTogcmVxLmJvZHksIHJlcUJvZHlUeXBlOiB0eXBlb2YgcmVxLmJvZHksIHJlcU1ldGhvZDogcmVxLm1ldGhvZCwgcmVxVXJsOiByZXEudXJsIH0sXG4gICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgICAgc2Vzc2lvbklkOiAnZGVidWctc2Vzc2lvbicsXG4gICAgICAgIGh5cG90aGVzaXNJZDogJ0EnLFxuICAgICAgfSksXG4gICAgfSkuY2F0Y2goKCkgPT4ge30pO1xuICB9XG4gIC8vICNlbmRyZWdpb25cblxuICBjb25zdCB0b2tlbkRlbGl2ZXJ5ID0gY29uZmlnLnRva2VuRGVsaXZlcnk7XG4gIGNvbnN0IGJhc2VVcmwgPSBjb25maWcuYmFzZVVybDtcbiAgY29uc3QgZW5kcG9pbnRzID0gY29uZmlnLmVuZHBvaW50cyA/PyB7fTtcbiAgY29uc3QgcmVmcmVzaFBhdGggPSBlbmRwb2ludHMucmVmcmVzaCA/PyAnL3JlZnJlc2gnO1xuICBjb25zdCBsb2dpblBhdGggPSBlbmRwb2ludHMubG9naW4gPz8gJy9sb2dpbic7XG4gIGNvbnN0IHNpZ251cFBhdGggPSBlbmRwb2ludHMuc2lnbnVwID8/ICcvc2lnbnVwJztcbiAgY29uc3Qgc29jaWFsRXhjaGFuZ2VQYXRoID0gZW5kcG9pbnRzLnNvY2lhbEV4Y2hhbmdlID8/ICcvc29jaWFsL2V4Y2hhbmdlJztcbiAgY29uc3QgcmVmcmVzaFVybCA9IGAke2Jhc2VVcmx9JHtyZWZyZXNoUGF0aH1gO1xuXG4gIGNvbnN0IGlzQXV0aEFwaVJlcXVlc3QgPSByZXEudXJsLmluY2x1ZGVzKGJhc2VVcmwpO1xuICBjb25zdCBpc1JlZnJlc2hFbmRwb2ludCA9IHJlcS51cmwuaW5jbHVkZXMocmVmcmVzaFBhdGgpO1xuICBjb25zdCBpc1B1YmxpY0VuZHBvaW50ID1cbiAgICByZXEudXJsLmluY2x1ZGVzKGxvZ2luUGF0aCkgfHwgcmVxLnVybC5pbmNsdWRlcyhzaWdudXBQYXRoKSB8fCByZXEudXJsLmluY2x1ZGVzKHNvY2lhbEV4Y2hhbmdlUGF0aCk7XG5cbiAgLy8gQnVpbGQgcmVxdWVzdCB3aXRoIGNyZWRlbnRpYWxzIChjb29raWVzIG1vZGUgb25seSlcbiAgbGV0IGF1dGhSZXEgPSByZXE7XG4gIGlmICh0b2tlbkRlbGl2ZXJ5ID09PSAnY29va2llcycpIHtcbiAgICBhdXRoUmVxID0gYXV0aFJlcS5jbG9uZSh7IHdpdGhDcmVkZW50aWFsczogdHJ1ZSB9KTtcblxuICAgIGlmIChbJ1BPU1QnLCAnUFVUJywgJ1BBVENIJywgJ0RFTEVURSddLmluY2x1ZGVzKHJlcS5tZXRob2QpKSB7XG4gICAgICBjb25zdCBjc3JmQ29va2llTmFtZSA9IGNvbmZpZy5jc3JmPy5jb29raWVOYW1lID8/ICduYXV0aF9jc3JmX3Rva2VuJztcbiAgICAgIGNvbnN0IGNzcmZIZWFkZXJOYW1lID0gY29uZmlnLmNzcmY/LmhlYWRlck5hbWUgPz8gJ3gtY3NyZi10b2tlbic7XG4gICAgICBjb25zdCBjc3JmVG9rZW4gPSBnZXRDc3JmVG9rZW4oY3NyZkNvb2tpZU5hbWUpO1xuICAgICAgaWYgKGNzcmZUb2tlbikge1xuICAgICAgICBhdXRoUmVxID0gYXV0aFJlcS5jbG9uZSh7IHNldEhlYWRlcnM6IHsgW2NzcmZIZWFkZXJOYW1lXTogY3NyZlRva2VuIH0gfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5leHQoYXV0aFJlcSkucGlwZShcbiAgICBjYXRjaEVycm9yKChlcnJvcjogdW5rbm93bikgPT4ge1xuICAgICAgY29uc3Qgc2hvdWxkSGFuZGxlID1cbiAgICAgICAgZXJyb3IgaW5zdGFuY2VvZiBIdHRwRXJyb3JSZXNwb25zZSAmJlxuICAgICAgICBlcnJvci5zdGF0dXMgPT09IDQwMSAmJlxuICAgICAgICBpc0F1dGhBcGlSZXF1ZXN0ICYmXG4gICAgICAgICFpc1JlZnJlc2hFbmRwb2ludCAmJlxuICAgICAgICAhaXNQdWJsaWNFbmRwb2ludCAmJlxuICAgICAgICAhcmV0cmllZFJlcXVlc3RzLmhhcyhyZXEpO1xuXG4gICAgICBpZiAoIXNob3VsZEhhbmRsZSkge1xuICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XG4gICAgICB9XG5cbiAgICAgIC8vIE1hcmsgb3JpZ2luYWwgcmVxdWVzdCBhcyByZXRyaWVkIHRvIHByZXZlbnQgaW5maW5pdGUgbG9vcHNcbiAgICAgIHJldHJpZWRSZXF1ZXN0cy5hZGQocmVxKTtcblxuICAgICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgICBjb25zb2xlLndhcm4oJ1tuYXV0aC1pbnRlcmNlcHRvcl0gNDAxIGRldGVjdGVkOicsIHJlcS51cmwpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWlzUmVmcmVzaGluZykge1xuICAgICAgICBpc1JlZnJlc2hpbmcgPSB0cnVlO1xuICAgICAgICByZWZyZXNoVG9rZW5TdWJqZWN0Lm5leHQobnVsbCk7XG5cbiAgICAgICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgICAgIGNvbnNvbGUud2FybignW25hdXRoLWludGVyY2VwdG9yXSBTdGFydGluZyByZWZyZXNoLi4uJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZWZyZXNoIGJhc2VkIG9uIG1vZGVcbiAgICAgICAgY29uc3QgcmVmcmVzaCQgPVxuICAgICAgICAgIHRva2VuRGVsaXZlcnkgPT09ICdjb29raWVzJ1xuICAgICAgICAgICAgPyBodHRwLnBvc3Q8eyBhY2Nlc3NUb2tlbj86IHN0cmluZyB9PihyZWZyZXNoVXJsLCB7fSwgeyB3aXRoQ3JlZGVudGlhbHM6IHRydWUgfSlcbiAgICAgICAgICAgIDogZnJvbShhdXRoU2VydmljZS5yZWZyZXNoKCkpO1xuXG4gICAgICAgIHJldHVybiByZWZyZXNoJC5waXBlKFxuICAgICAgICAgIHN3aXRjaE1hcCgocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdbbmF1dGgtaW50ZXJjZXB0b3JdIFJlZnJlc2ggc3VjY2Vzc2Z1bCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaXNSZWZyZXNoaW5nID0gZmFsc2U7XG5cbiAgICAgICAgICAgIC8vIEdldCBuZXcgdG9rZW4gKEpTT04gbW9kZSkgb3Igc2lnbmFsIHN1Y2Nlc3MgKGNvb2tpZXMgbW9kZSlcbiAgICAgICAgICAgIGNvbnN0IG5ld1Rva2VuID0gJ2FjY2Vzc1Rva2VuJyBpbiByZXNwb25zZSA/IHJlc3BvbnNlLmFjY2Vzc1Rva2VuIDogJ3N1Y2Nlc3MnO1xuICAgICAgICAgICAgcmVmcmVzaFRva2VuU3ViamVjdC5uZXh0KG5ld1Rva2VuID8/ICdzdWNjZXNzJyk7XG5cbiAgICAgICAgICAgIC8vICNyZWdpb24gYWdlbnQgbG9nXG4gICAgICAgICAgICBmZXRjaCgnaHR0cDovLzEyNy4wLjAuMTo3MjQyL2luZ2VzdC85N2Y5ZmU1My02YThiLTQzZTItYWU5Yi00YjJkMGY3MjU4MTYnLCB7XG4gICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICBoZWFkZXJzOiB7ICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicgfSxcbiAgICAgICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgIGxvY2F0aW9uOiAnYXV0aC5pbnRlcmNlcHRvci50czoxMjUnLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6ICdCZWZvcmUgYnVpbGRSZXRyeVJlcXVlc3QnLFxuICAgICAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICAgIGF1dGhSZXFCb2R5OiBhdXRoUmVxLmJvZHksXG4gICAgICAgICAgICAgICAgICBhdXRoUmVxTWV0aG9kOiBhdXRoUmVxLm1ldGhvZCxcbiAgICAgICAgICAgICAgICAgIGF1dGhSZXFVcmw6IGF1dGhSZXEudXJsLFxuICAgICAgICAgICAgICAgICAgYXV0aFJlcUJvZHlUeXBlOiB0eXBlb2YgYXV0aFJlcS5ib2R5LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgICAgIHNlc3Npb25JZDogJ2RlYnVnLXNlc3Npb24nLFxuICAgICAgICAgICAgICAgIGh5cG90aGVzaXNJZDogJ0EnLFxuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIH0pLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgICAgICAgIC8vICNlbmRyZWdpb25cblxuICAgICAgICAgICAgLy8gQnVpbGQgcmV0cnkgcmVxdWVzdCB3aXRoIGZyZXNoIENTUkYgdG9rZW4gKHJlLXJlYWQgZnJvbSBjb29raWUgYWZ0ZXIgcmVmcmVzaClcbiAgICAgICAgICAgIGNvbnN0IHJldHJ5UmVxID0gYnVpbGRSZXRyeVJlcXVlc3QoYXV0aFJlcSwgdG9rZW5EZWxpdmVyeSwgbmV3VG9rZW4sIGNvbmZpZy5jc3JmKTtcblxuICAgICAgICAgICAgLy8gI3JlZ2lvbiBhZ2VudCBsb2dcbiAgICAgICAgICAgIGZldGNoKCdodHRwOi8vMTI3LjAuMC4xOjcyNDIvaW5nZXN0Lzk3ZjlmZTUzLTZhOGItNDNlMi1hZTliLTRiMmQwZjcyNTgxNicsIHtcbiAgICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9LFxuICAgICAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgbG9jYXRpb246ICdhdXRoLmludGVyY2VwdG9yLnRzOjEzMCcsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogJ0FmdGVyIGJ1aWxkUmV0cnlSZXF1ZXN0JyxcbiAgICAgICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgICByZXRyeVJlcUJvZHk6IHJldHJ5UmVxLmJvZHksXG4gICAgICAgICAgICAgICAgICByZXRyeVJlcU1ldGhvZDogcmV0cnlSZXEubWV0aG9kLFxuICAgICAgICAgICAgICAgICAgcmV0cnlSZXFVcmw6IHJldHJ5UmVxLnVybCxcbiAgICAgICAgICAgICAgICAgIHJldHJ5UmVxQm9keVR5cGU6IHR5cGVvZiByZXRyeVJlcS5ib2R5LFxuICAgICAgICAgICAgICAgICAgaGVhZGVyc0tleXM6IHJldHJ5UmVxLmhlYWRlcnMua2V5cygpLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgICAgIHNlc3Npb25JZDogJ2RlYnVnLXNlc3Npb24nLFxuICAgICAgICAgICAgICAgIGh5cG90aGVzaXNJZDogJ0InLFxuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIH0pLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgICAgICAgIC8vICNlbmRyZWdpb25cblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tuYXV0aC1pbnRlcmNlcHRvcl0gUmV0cnlpbmc6JywgcmVxLnVybCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFJldHJ5IHRoZSByZXF1ZXN0IHdpdGggZnJlc2ggdG9rZW4vQ1NSRlxuICAgICAgICAgICAgLy8gSU1QT1JUQU5UOiBFcnJvcnMgZnJvbSB0aGUgcmV0cnkgKGUuZy4sIDQwMCB2YWxpZGF0aW9uKSBzaG91bGQgTk9UIHRyaWdnZXJcbiAgICAgICAgICAgIC8vIHNlc3Npb24gZXhwaXJhdGlvbiByZWRpcmVjdC4gT25seSB0aGUgcmVmcmVzaCBmYWlsdXJlIHNob3VsZCByZWRpcmVjdC5cbiAgICAgICAgICAgIHJldHVybiBuZXh0KHJldHJ5UmVxKS5waXBlKFxuICAgICAgICAgICAgICBjYXRjaEVycm9yKChyZXRyeUVycikgPT4ge1xuICAgICAgICAgICAgICAgIC8vIFJldHJ5IGZhaWxlZCAoY291bGQgYmUgNDAwLCA0MDMsIDUwMCwgZXRjLilcbiAgICAgICAgICAgICAgICAvLyBKdXN0IHByb3BhZ2F0ZSB0aGUgZXJyb3IgLSBkb24ndCByZWRpcmVjdCB0byBsb2dpblxuICAgICAgICAgICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignW25hdXRoLWludGVyY2VwdG9yXSBSZXRyeSByZXF1ZXN0IGZhaWxlZDonLCByZXRyeUVycik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IHJldHJ5RXJyKTtcbiAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pLFxuICAgICAgICAgIGNhdGNoRXJyb3IoKGVycikgPT4ge1xuICAgICAgICAgICAgLy8gVGhpcyBvbmx5IGNhdGNoZXMgUkVGUkVTSCBmYWlsdXJlcywgbm90IHJldHJ5IGZhaWx1cmVzXG4gICAgICAgICAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1tuYXV0aC1pbnRlcmNlcHRvcl0gUmVmcmVzaCBmYWlsZWQ6JywgZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlzUmVmcmVzaGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmVmcmVzaFRva2VuU3ViamVjdC5uZXh0KG51bGwpO1xuXG4gICAgICAgICAgICAvLyBIYW5kbGUgc2Vzc2lvbiBleHBpcmF0aW9uIC0gcmVkaXJlY3QgdG8gY29uZmlndXJlZCBVUkxcbiAgICAgICAgICAgIC8vIE9ubHkgcmVkaXJlY3QgaWYgcmVmcmVzaCBpdHNlbGYgZmFpbGVkIChub3QgaWYgcmV0cnkgZmFpbGVkKVxuICAgICAgICAgICAgaWYgKGNvbmZpZy5yZWRpcmVjdHM/LnNlc3Npb25FeHBpcmVkKSB7XG4gICAgICAgICAgICAgIHJvdXRlci5uYXZpZ2F0ZUJ5VXJsKGNvbmZpZy5yZWRpcmVjdHMuc2Vzc2lvbkV4cGlyZWQpLmNhdGNoKChuYXZFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1tuYXV0aC1pbnRlcmNlcHRvcl0gTmF2aWdhdGlvbiBmYWlsZWQ6JywgbmF2RXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGVycik7XG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBXYWl0IGZvciBvbmdvaW5nIHJlZnJlc2hcbiAgICAgICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgICAgIGNvbnNvbGUud2FybignW25hdXRoLWludGVyY2VwdG9yXSBXYWl0aW5nIGZvciByZWZyZXNoLi4uJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlZnJlc2hUb2tlblN1YmplY3QucGlwZShcbiAgICAgICAgICBmaWx0ZXIoKHRva2VuKTogdG9rZW4gaXMgc3RyaW5nID0+IHRva2VuICE9PSBudWxsKSxcbiAgICAgICAgICB0YWtlKDEpLFxuICAgICAgICAgIHN3aXRjaE1hcCgodG9rZW4pID0+IHtcbiAgICAgICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdbbmF1dGgtaW50ZXJjZXB0b3JdIFJlZnJlc2ggZG9uZSwgcmV0cnlpbmc6JywgcmVxLnVybCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXRyeVJlcSA9IGJ1aWxkUmV0cnlSZXF1ZXN0KGF1dGhSZXEsIHRva2VuRGVsaXZlcnksIHRva2VuLCBjb25maWcuY3NyZik7XG5cbiAgICAgICAgICAgIC8vIFJldHJ5IHRoZSByZXF1ZXN0IC0gZXJyb3JzIGhlcmUgc2hvdWxkIHByb3BhZ2F0ZSBub3JtYWxseVxuICAgICAgICAgICAgLy8gd2l0aG91dCB0cmlnZ2VyaW5nIHNlc3Npb24gZXhwaXJhdGlvbiByZWRpcmVjdFxuICAgICAgICAgICAgcmV0dXJuIG5leHQocmV0cnlSZXEpLnBpcGUoXG4gICAgICAgICAgICAgIGNhdGNoRXJyb3IoKHJldHJ5RXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdbbmF1dGgtaW50ZXJjZXB0b3JdIFJldHJ5IHJlcXVlc3QgZmFpbGVkOicsIHJldHJ5RXJyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gcmV0cnlFcnIpO1xuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSksXG4gICk7XG59O1xuXG4vKipcbiAqIEJ1aWxkIHJldHJ5IHJlcXVlc3Qgd2l0aCBhcHByb3ByaWF0ZSBhdXRoLlxuICpcbiAqIENSSVRJQ0FMIEZJWDogSW4gY29va2llcyBtb2RlLCBhZnRlciByZWZyZXNoIHRoZSBzZXJ2ZXIgbWF5IHNlbmQgdXBkYXRlZCBjb29raWVzLlxuICogV2UgTVVTVCByZS1yZWFkIHRoZSBDU1JGIHRva2VuIGZyb20gdGhlIGNvb2tpZSBiZWZvcmUgcmV0cnlpbmcgdG8gZW5zdXJlIHdlIGhhdmVcbiAqIHRoZSBjdXJyZW50IENTUkYgdG9rZW4gdGhhdCBtYXRjaGVzIHdoYXQgdGhlIHNlcnZlciBleHBlY3RzLlxuICpcbiAqIEluIEpTT04gbW9kZTogQ2xvbmVzIHRoZSByZXF1ZXN0IGFuZCBhZGRzIHRoZSBuZXcgQmVhcmVyIHRva2VuLlxuICpcbiAqIEBwYXJhbSBvcmlnaW5hbFJlcSAtIFRoZSBiYXNlIHJlcXVlc3QgKGFscmVhZHkgaGFzIHdpdGhDcmVkZW50aWFscyBpZiBjb29raWVzIG1vZGUpXG4gKiBAcGFyYW0gdG9rZW5EZWxpdmVyeSAtICdjb29raWVzJyBvciAnanNvbidcbiAqIEBwYXJhbSBuZXdUb2tlbiAtIFRoZSBuZXcgYWNjZXNzIHRva2VuIChKU09OIG1vZGUgb25seSlcbiAqIEBwYXJhbSBjc3JmQ29uZmlnIC0gQ1NSRiBjb25maWd1cmF0aW9uIHRvIHJlLXJlYWQgdG9rZW4gZnJvbSBjb29raWVcbiAqIEByZXR1cm5zIFRoZSByZXF1ZXN0IHJlYWR5IGZvciByZXRyeSB3aXRoIGZyZXNoIGF1dGhcbiAqL1xuZnVuY3Rpb24gYnVpbGRSZXRyeVJlcXVlc3QoXG4gIG9yaWdpbmFsUmVxOiBIdHRwUmVxdWVzdDx1bmtub3duPixcbiAgdG9rZW5EZWxpdmVyeTogc3RyaW5nLFxuICBuZXdUb2tlbj86IHN0cmluZyxcbiAgY3NyZkNvbmZpZz86IHsgY29va2llTmFtZT86IHN0cmluZzsgaGVhZGVyTmFtZT86IHN0cmluZyB9LFxuKTogSHR0cFJlcXVlc3Q8dW5rbm93bj4ge1xuICBpZiAodG9rZW5EZWxpdmVyeSA9PT0gJ2pzb24nICYmIG5ld1Rva2VuICYmIG5ld1Rva2VuICE9PSAnc3VjY2VzcycpIHtcbiAgICByZXR1cm4gb3JpZ2luYWxSZXEuY2xvbmUoe1xuICAgICAgc2V0SGVhZGVyczogeyBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7bmV3VG9rZW59YCB9LFxuICAgIH0pO1xuICB9XG5cbiAgLy8gQ29va2llcyBtb2RlOiBCcm93c2VyIGF1dG9tYXRpY2FsbHkgc2VuZHMgdXBkYXRlZCBodHRwT25seSBjb29raWVzIChhY2Nlc3MvcmVmcmVzaCB0b2tlbnMpLlxuICAvLyBIb3dldmVyLCBDU1JGIHRva2VuIG11c3QgbWF0Y2ggdGhlIGNvb2tpZSB2YWx1ZSBhdCB0aGUgbW9tZW50IG9mIHJldHJ5LlxuICAvLyBXZSBBTFdBWVMgcmUtcmVhZCBmcm9tIGRvY3VtZW50LmNvb2tpZSBoZXJlICh1c2luZyBkZWZhdWx0cyB3aGVuIGNzcmZDb25maWdcbiAgLy8gaXMgbm90IHByb3ZpZGVkKSB0byBhdm9pZCBzdGFsZSBoZWFkZXIgdmFsdWVzIGFmdGVyIHJlZnJlc2ggb3IgYWNyb3NzIHRhYnMuXG4gIGlmICh0b2tlbkRlbGl2ZXJ5ID09PSAnY29va2llcycgJiYgWydQT1NUJywgJ1BVVCcsICdQQVRDSCcsICdERUxFVEUnXS5pbmNsdWRlcyhvcmlnaW5hbFJlcS5tZXRob2QpKSB7XG4gICAgY29uc3QgY3NyZkNvb2tpZU5hbWUgPSBjc3JmQ29uZmlnPy5jb29raWVOYW1lID8/ICduYXV0aF9jc3JmX3Rva2VuJztcbiAgICBjb25zdCBjc3JmSGVhZGVyTmFtZSA9IGNzcmZDb25maWc/LmhlYWRlck5hbWUgPz8gJ3gtY3NyZi10b2tlbic7XG4gICAgY29uc3QgZnJlc2hDc3JmVG9rZW4gPSBnZXRDc3JmVG9rZW4oY3NyZkNvb2tpZU5hbWUpO1xuXG4gICAgLy8gI3JlZ2lvbiBhZ2VudCBsb2dcbiAgICBmZXRjaCgnaHR0cDovLzEyNy4wLjAuMTo3MjQyL2luZ2VzdC85N2Y5ZmU1My02YThiLTQzZTItYWU5Yi00YjJkMGY3MjU4MTYnLCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9LFxuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICBsb2NhdGlvbjogJ2F1dGguaW50ZXJjZXB0b3IudHM6YnVpbGRSZXRyeVJlcXVlc3QnLFxuICAgICAgICBtZXNzYWdlOiAnSW5zaWRlIGJ1aWxkUmV0cnlSZXF1ZXN0IGNvb2tpZXMgYnJhbmNoJyxcbiAgICAgICAgZGF0YToge1xuICAgICAgICAgIG9yaWdpbmFsUmVxQm9keTogb3JpZ2luYWxSZXEuYm9keSxcbiAgICAgICAgICBvcmlnaW5hbFJlcUJvZHlUeXBlOiB0eXBlb2Ygb3JpZ2luYWxSZXEuYm9keSxcbiAgICAgICAgICBmcmVzaENzcmZUb2tlbjogZnJlc2hDc3JmVG9rZW4/LnN1YnN0cmluZygwLCA4KSxcbiAgICAgICAgICBtZXRob2Q6IG9yaWdpbmFsUmVxLm1ldGhvZCxcbiAgICAgICAgfSxcbiAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICBzZXNzaW9uSWQ6ICdkZWJ1Zy1zZXNzaW9uJyxcbiAgICAgICAgaHlwb3RoZXNpc0lkOiAnQycsXG4gICAgICB9KSxcbiAgICB9KS5jYXRjaCgoKSA9PiB7fSk7XG4gICAgLy8gI2VuZHJlZ2lvblxuXG4gICAgaWYgKGZyZXNoQ3NyZlRva2VuKSB7XG4gICAgICAvLyBDbG9uZSB3aXRoIGZyZXNoIENTUkYgdG9rZW4gaW4gaGVhZGVyXG4gICAgICBjb25zdCBjbG9uZWQgPSBvcmlnaW5hbFJlcS5jbG9uZSh7XG4gICAgICAgIHNldEhlYWRlcnM6IHsgW2NzcmZIZWFkZXJOYW1lXTogZnJlc2hDc3JmVG9rZW4gfSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyAjcmVnaW9uIGFnZW50IGxvZ1xuICAgICAgZmV0Y2goJ2h0dHA6Ly8xMjcuMC4wLjE6NzI0Mi9pbmdlc3QvOTdmOWZlNTMtNmE4Yi00M2UyLWFlOWItNGIyZDBmNzI1ODE2Jywge1xuICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nIH0sXG4gICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICBsb2NhdGlvbjogJ2F1dGguaW50ZXJjZXB0b3IudHM6YnVpbGRSZXRyeVJlcXVlc3Q6YWZ0ZXJDbG9uZScsXG4gICAgICAgICAgbWVzc2FnZTogJ0FmdGVyIGNsb25lIHdpdGggc2V0SGVhZGVycycsXG4gICAgICAgICAgZGF0YTogeyBjbG9uZWRCb2R5OiBjbG9uZWQuYm9keSwgY2xvbmVkQm9keVR5cGU6IHR5cGVvZiBjbG9uZWQuYm9keSwgb3JpZ2luYWxCb2R5OiBvcmlnaW5hbFJlcS5ib2R5IH0sXG4gICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgIHNlc3Npb25JZDogJ2RlYnVnLXNlc3Npb24nLFxuICAgICAgICAgIGh5cG90aGVzaXNJZDogJ0QnLFxuICAgICAgICB9KSxcbiAgICAgIH0pLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgIC8vICNlbmRyZWdpb25cblxuICAgICAgcmV0dXJuIGNsb25lZDtcbiAgICB9XG4gIH1cblxuICAvLyBObyBjaGFuZ2VzIG5lZWRlZCAoR0VUIHJlcXVlc3Qgb3Igbm8gQ1NSRiB0b2tlbiBhdmFpbGFibGUpXG4gIHJldHVybiBvcmlnaW5hbFJlcTtcbn1cblxuLyoqXG4gKiBDbGFzcy1iYXNlZCBpbnRlcmNlcHRvciBmb3IgTmdNb2R1bGUgY29tcGF0aWJpbGl0eS5cbiAqL1xuZXhwb3J0IGNsYXNzIEF1dGhJbnRlcmNlcHRvciB7XG4gIGludGVyY2VwdChyZXE6IEh0dHBSZXF1ZXN0PHVua25vd24+LCBuZXh0OiBIdHRwSGFuZGxlckZuKSB7XG4gICAgcmV0dXJuIGF1dGhJbnRlcmNlcHRvcihyZXEsIG5leHQpO1xuICB9XG59XG4iXX0=
|
|
@@ -1256,6 +1256,22 @@ const authInterceptor = (req, next) => {
|
|
|
1256
1256
|
if (!isBrowser) {
|
|
1257
1257
|
return next(req);
|
|
1258
1258
|
}
|
|
1259
|
+
// #region agent log
|
|
1260
|
+
if (req.url.includes('/profile') && req.method === 'PUT') {
|
|
1261
|
+
fetch('http://127.0.0.1:7242/ingest/97f9fe53-6a8b-43e2-ae9b-4b2d0f725816', {
|
|
1262
|
+
method: 'POST',
|
|
1263
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1264
|
+
body: JSON.stringify({
|
|
1265
|
+
location: 'auth.interceptor.ts:entry',
|
|
1266
|
+
message: 'Original request entry',
|
|
1267
|
+
data: { reqBody: req.body, reqBodyType: typeof req.body, reqMethod: req.method, reqUrl: req.url },
|
|
1268
|
+
timestamp: Date.now(),
|
|
1269
|
+
sessionId: 'debug-session',
|
|
1270
|
+
hypothesisId: 'A',
|
|
1271
|
+
}),
|
|
1272
|
+
}).catch(() => { });
|
|
1273
|
+
}
|
|
1274
|
+
// #endregion
|
|
1259
1275
|
const tokenDelivery = config.tokenDelivery;
|
|
1260
1276
|
const baseUrl = config.baseUrl;
|
|
1261
1277
|
const endpoints = config.endpoints ?? {};
|
|
@@ -1290,6 +1306,8 @@ const authInterceptor = (req, next) => {
|
|
|
1290
1306
|
if (!shouldHandle) {
|
|
1291
1307
|
return throwError(() => error);
|
|
1292
1308
|
}
|
|
1309
|
+
// Mark original request as retried to prevent infinite loops
|
|
1310
|
+
retriedRequests.add(req);
|
|
1293
1311
|
if (config.debug) {
|
|
1294
1312
|
console.warn('[nauth-interceptor] 401 detected:', req.url);
|
|
1295
1313
|
}
|
|
@@ -1311,20 +1329,70 @@ const authInterceptor = (req, next) => {
|
|
|
1311
1329
|
// Get new token (JSON mode) or signal success (cookies mode)
|
|
1312
1330
|
const newToken = 'accessToken' in response ? response.accessToken : 'success';
|
|
1313
1331
|
refreshTokenSubject.next(newToken ?? 'success');
|
|
1314
|
-
//
|
|
1315
|
-
|
|
1316
|
-
|
|
1332
|
+
// #region agent log
|
|
1333
|
+
fetch('http://127.0.0.1:7242/ingest/97f9fe53-6a8b-43e2-ae9b-4b2d0f725816', {
|
|
1334
|
+
method: 'POST',
|
|
1335
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1336
|
+
body: JSON.stringify({
|
|
1337
|
+
location: 'auth.interceptor.ts:125',
|
|
1338
|
+
message: 'Before buildRetryRequest',
|
|
1339
|
+
data: {
|
|
1340
|
+
authReqBody: authReq.body,
|
|
1341
|
+
authReqMethod: authReq.method,
|
|
1342
|
+
authReqUrl: authReq.url,
|
|
1343
|
+
authReqBodyType: typeof authReq.body,
|
|
1344
|
+
},
|
|
1345
|
+
timestamp: Date.now(),
|
|
1346
|
+
sessionId: 'debug-session',
|
|
1347
|
+
hypothesisId: 'A',
|
|
1348
|
+
}),
|
|
1349
|
+
}).catch(() => { });
|
|
1350
|
+
// #endregion
|
|
1351
|
+
// Build retry request with fresh CSRF token (re-read from cookie after refresh)
|
|
1352
|
+
const retryReq = buildRetryRequest(authReq, tokenDelivery, newToken, config.csrf);
|
|
1353
|
+
// #region agent log
|
|
1354
|
+
fetch('http://127.0.0.1:7242/ingest/97f9fe53-6a8b-43e2-ae9b-4b2d0f725816', {
|
|
1355
|
+
method: 'POST',
|
|
1356
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1357
|
+
body: JSON.stringify({
|
|
1358
|
+
location: 'auth.interceptor.ts:130',
|
|
1359
|
+
message: 'After buildRetryRequest',
|
|
1360
|
+
data: {
|
|
1361
|
+
retryReqBody: retryReq.body,
|
|
1362
|
+
retryReqMethod: retryReq.method,
|
|
1363
|
+
retryReqUrl: retryReq.url,
|
|
1364
|
+
retryReqBodyType: typeof retryReq.body,
|
|
1365
|
+
headersKeys: retryReq.headers.keys(),
|
|
1366
|
+
},
|
|
1367
|
+
timestamp: Date.now(),
|
|
1368
|
+
sessionId: 'debug-session',
|
|
1369
|
+
hypothesisId: 'B',
|
|
1370
|
+
}),
|
|
1371
|
+
}).catch(() => { });
|
|
1372
|
+
// #endregion
|
|
1317
1373
|
if (config.debug) {
|
|
1318
1374
|
console.warn('[nauth-interceptor] Retrying:', req.url);
|
|
1319
1375
|
}
|
|
1320
|
-
|
|
1376
|
+
// Retry the request with fresh token/CSRF
|
|
1377
|
+
// IMPORTANT: Errors from the retry (e.g., 400 validation) should NOT trigger
|
|
1378
|
+
// session expiration redirect. Only the refresh failure should redirect.
|
|
1379
|
+
return next(retryReq).pipe(catchError((retryErr) => {
|
|
1380
|
+
// Retry failed (could be 400, 403, 500, etc.)
|
|
1381
|
+
// Just propagate the error - don't redirect to login
|
|
1382
|
+
if (config.debug) {
|
|
1383
|
+
console.warn('[nauth-interceptor] Retry request failed:', retryErr);
|
|
1384
|
+
}
|
|
1385
|
+
return throwError(() => retryErr);
|
|
1386
|
+
}));
|
|
1321
1387
|
}), catchError((err) => {
|
|
1388
|
+
// This only catches REFRESH failures, not retry failures
|
|
1322
1389
|
if (config.debug) {
|
|
1323
1390
|
console.error('[nauth-interceptor] Refresh failed:', err);
|
|
1324
1391
|
}
|
|
1325
1392
|
isRefreshing = false;
|
|
1326
1393
|
refreshTokenSubject.next(null);
|
|
1327
1394
|
// Handle session expiration - redirect to configured URL
|
|
1395
|
+
// Only redirect if refresh itself failed (not if retry failed)
|
|
1328
1396
|
if (config.redirects?.sessionExpired) {
|
|
1329
1397
|
router.navigateByUrl(config.redirects.sessionExpired).catch((navError) => {
|
|
1330
1398
|
if (config.debug) {
|
|
@@ -1344,23 +1412,91 @@ const authInterceptor = (req, next) => {
|
|
|
1344
1412
|
if (config.debug) {
|
|
1345
1413
|
console.warn('[nauth-interceptor] Refresh done, retrying:', req.url);
|
|
1346
1414
|
}
|
|
1347
|
-
const retryReq = buildRetryRequest(authReq, tokenDelivery, token);
|
|
1348
|
-
|
|
1349
|
-
|
|
1415
|
+
const retryReq = buildRetryRequest(authReq, tokenDelivery, token, config.csrf);
|
|
1416
|
+
// Retry the request - errors here should propagate normally
|
|
1417
|
+
// without triggering session expiration redirect
|
|
1418
|
+
return next(retryReq).pipe(catchError((retryErr) => {
|
|
1419
|
+
if (config.debug) {
|
|
1420
|
+
console.warn('[nauth-interceptor] Retry request failed:', retryErr);
|
|
1421
|
+
}
|
|
1422
|
+
return throwError(() => retryErr);
|
|
1423
|
+
}));
|
|
1350
1424
|
}));
|
|
1351
1425
|
}
|
|
1352
1426
|
}));
|
|
1353
1427
|
};
|
|
1354
1428
|
/**
|
|
1355
1429
|
* Build retry request with appropriate auth.
|
|
1430
|
+
*
|
|
1431
|
+
* CRITICAL FIX: In cookies mode, after refresh the server may send updated cookies.
|
|
1432
|
+
* We MUST re-read the CSRF token from the cookie before retrying to ensure we have
|
|
1433
|
+
* the current CSRF token that matches what the server expects.
|
|
1434
|
+
*
|
|
1435
|
+
* In JSON mode: Clones the request and adds the new Bearer token.
|
|
1436
|
+
*
|
|
1437
|
+
* @param originalReq - The base request (already has withCredentials if cookies mode)
|
|
1438
|
+
* @param tokenDelivery - 'cookies' or 'json'
|
|
1439
|
+
* @param newToken - The new access token (JSON mode only)
|
|
1440
|
+
* @param csrfConfig - CSRF configuration to re-read token from cookie
|
|
1441
|
+
* @returns The request ready for retry with fresh auth
|
|
1356
1442
|
*/
|
|
1357
|
-
function buildRetryRequest(originalReq, tokenDelivery, newToken) {
|
|
1443
|
+
function buildRetryRequest(originalReq, tokenDelivery, newToken, csrfConfig) {
|
|
1358
1444
|
if (tokenDelivery === 'json' && newToken && newToken !== 'success') {
|
|
1359
1445
|
return originalReq.clone({
|
|
1360
1446
|
setHeaders: { Authorization: `Bearer ${newToken}` },
|
|
1361
1447
|
});
|
|
1362
1448
|
}
|
|
1363
|
-
|
|
1449
|
+
// Cookies mode: Browser automatically sends updated httpOnly cookies (access/refresh tokens).
|
|
1450
|
+
// However, CSRF token must match the cookie value at the moment of retry.
|
|
1451
|
+
// We ALWAYS re-read from document.cookie here (using defaults when csrfConfig
|
|
1452
|
+
// is not provided) to avoid stale header values after refresh or across tabs.
|
|
1453
|
+
if (tokenDelivery === 'cookies' && ['POST', 'PUT', 'PATCH', 'DELETE'].includes(originalReq.method)) {
|
|
1454
|
+
const csrfCookieName = csrfConfig?.cookieName ?? 'nauth_csrf_token';
|
|
1455
|
+
const csrfHeaderName = csrfConfig?.headerName ?? 'x-csrf-token';
|
|
1456
|
+
const freshCsrfToken = getCsrfToken(csrfCookieName);
|
|
1457
|
+
// #region agent log
|
|
1458
|
+
fetch('http://127.0.0.1:7242/ingest/97f9fe53-6a8b-43e2-ae9b-4b2d0f725816', {
|
|
1459
|
+
method: 'POST',
|
|
1460
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1461
|
+
body: JSON.stringify({
|
|
1462
|
+
location: 'auth.interceptor.ts:buildRetryRequest',
|
|
1463
|
+
message: 'Inside buildRetryRequest cookies branch',
|
|
1464
|
+
data: {
|
|
1465
|
+
originalReqBody: originalReq.body,
|
|
1466
|
+
originalReqBodyType: typeof originalReq.body,
|
|
1467
|
+
freshCsrfToken: freshCsrfToken?.substring(0, 8),
|
|
1468
|
+
method: originalReq.method,
|
|
1469
|
+
},
|
|
1470
|
+
timestamp: Date.now(),
|
|
1471
|
+
sessionId: 'debug-session',
|
|
1472
|
+
hypothesisId: 'C',
|
|
1473
|
+
}),
|
|
1474
|
+
}).catch(() => { });
|
|
1475
|
+
// #endregion
|
|
1476
|
+
if (freshCsrfToken) {
|
|
1477
|
+
// Clone with fresh CSRF token in header
|
|
1478
|
+
const cloned = originalReq.clone({
|
|
1479
|
+
setHeaders: { [csrfHeaderName]: freshCsrfToken },
|
|
1480
|
+
});
|
|
1481
|
+
// #region agent log
|
|
1482
|
+
fetch('http://127.0.0.1:7242/ingest/97f9fe53-6a8b-43e2-ae9b-4b2d0f725816', {
|
|
1483
|
+
method: 'POST',
|
|
1484
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1485
|
+
body: JSON.stringify({
|
|
1486
|
+
location: 'auth.interceptor.ts:buildRetryRequest:afterClone',
|
|
1487
|
+
message: 'After clone with setHeaders',
|
|
1488
|
+
data: { clonedBody: cloned.body, clonedBodyType: typeof cloned.body, originalBody: originalReq.body },
|
|
1489
|
+
timestamp: Date.now(),
|
|
1490
|
+
sessionId: 'debug-session',
|
|
1491
|
+
hypothesisId: 'D',
|
|
1492
|
+
}),
|
|
1493
|
+
}).catch(() => { });
|
|
1494
|
+
// #endregion
|
|
1495
|
+
return cloned;
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
// No changes needed (GET request or no CSRF token available)
|
|
1499
|
+
return originalReq;
|
|
1364
1500
|
}
|
|
1365
1501
|
/**
|
|
1366
1502
|
* Class-based interceptor for NgModule compatibility.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nauth-toolkit-client-angular.mjs","sources":["../../src/ngmodule/tokens.ts","../../src/ngmodule/http-adapter.ts","../../src/ngmodule/auth.service.ts","../../src/ngmodule/auth.interceptor.class.ts","../../src/lib/auth.guard.ts","../../src/ngmodule/nauth.module.ts","../../src/lib/auth.interceptor.ts","../../src/lib/social-redirect-callback.guard.ts","../../src/public-api.ts","../../src/nauth-toolkit-client-angular.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport { NAuthClientConfig } from '@nauth-toolkit/client';\n\n/**\n * Injection token for providing NAuthClientConfig in Angular apps.\n */\nexport const NAUTH_CLIENT_CONFIG = new InjectionToken<NAuthClientConfig>('NAUTH_CLIENT_CONFIG');\n","import { Injectable } from '@angular/core';\nimport { HttpClient, HttpErrorResponse } from '@angular/common/http';\nimport { firstValueFrom } from 'rxjs';\nimport { HttpAdapter, HttpRequest, HttpResponse, NAuthClientError, NAuthErrorCode } from '@nauth-toolkit/client';\n\n/**\n * HTTP adapter for Angular using HttpClient.\n *\n * This adapter:\n * - Uses Angular's HttpClient for all requests\n * - Works with Angular's HTTP interceptors (including authInterceptor)\n * - Auto-provided via Angular DI (providedIn: 'root')\n * - Converts HttpClient responses to HttpResponse format\n * - Converts HttpErrorResponse to NAuthClientError\n *\n * Users don't need to configure this manually - it's automatically\n * injected when using AuthService in Angular apps.\n *\n * @example\n * ```typescript\n * // Automatic usage (no manual setup needed)\n * // AuthService automatically injects AngularHttpAdapter\n * constructor(private auth: AuthService) {}\n * ```\n */\n@Injectable()\nexport class AngularHttpAdapter implements HttpAdapter {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Safely parse a JSON response body.\n *\n * Angular's fetch backend (`withFetch()`) will throw a raw `SyntaxError` if\n * `responseType: 'json'` is used and the backend returns HTML (common for\n * proxies, 502 pages, SSR fallbacks, or misrouted requests).\n *\n * To avoid crashing consumer apps, we always request as text and then parse\n * JSON only when the response actually looks like JSON.\n *\n * @param bodyText - Raw response body as text\n * @param contentType - Content-Type header value (if available)\n * @returns Parsed JSON value (unknown)\n * @throws {SyntaxError} When body is non-empty but not valid JSON\n */\n private parseJsonBody(bodyText: string, contentType: string | null): unknown {\n const trimmed = bodyText.trim();\n if (!trimmed) return null;\n\n // If it's clearly HTML, never attempt JSON.parse (some proxies mislabel Content-Type).\n if (trimmed.startsWith('<')) {\n return bodyText;\n }\n\n const looksLikeJson = trimmed.startsWith('{') || trimmed.startsWith('[');\n const isJsonContentType = typeof contentType === 'string' && contentType.toLowerCase().includes('application/json');\n\n if (!looksLikeJson && !isJsonContentType) {\n // Return raw text when it doesn't look like JSON (e.g., HTML error pages).\n return bodyText;\n }\n\n return JSON.parse(trimmed) as unknown;\n }\n\n /**\n * Execute HTTP request using Angular's HttpClient.\n *\n * @param config - Request configuration\n * @returns Response with parsed data\n * @throws NAuthClientError if request fails\n */\n async request<T>(config: HttpRequest): Promise<HttpResponse<T>> {\n try {\n // Use Angular's HttpClient - goes through ALL interceptors.\n // IMPORTANT: Use responseType 'text' to avoid raw JSON.parse crashes when\n // the backend returns HTML (seen in some proxy/SSR/misroute setups).\n const res = await firstValueFrom(\n this.http.request(config.method, config.url, {\n body: config.body,\n headers: config.headers,\n withCredentials: config.credentials === 'include',\n observe: 'response',\n responseType: 'text',\n }),\n );\n\n const contentType = res.headers?.get('content-type');\n const parsed = this.parseJsonBody(res.body ?? '', contentType);\n\n return {\n data: parsed as T,\n status: res.status,\n headers: {}, // Reserved for future header passthrough if needed\n };\n } catch (error) {\n if (error instanceof HttpErrorResponse) {\n // Convert Angular's HttpErrorResponse to NAuthClientError.\n // When using responseType 'text', `error.error` is typically a string.\n const contentType = error.headers?.get('content-type') ?? null;\n const rawBody = typeof error.error === 'string' ? error.error : '';\n const parsedError = this.parseJsonBody(rawBody, contentType);\n\n const errorData =\n typeof parsedError === 'object' && parsedError !== null ? (parsedError as Record<string, unknown>) : {};\n const code =\n typeof errorData['code'] === 'string' ? (errorData['code'] as NAuthErrorCode) : NAuthErrorCode.INTERNAL_ERROR;\n const message =\n typeof errorData['message'] === 'string'\n ? (errorData['message'] as string)\n : typeof parsedError === 'string' && parsedError.trim()\n ? parsedError\n : error.message || `Request failed with status ${error.status}`;\n const timestamp = typeof errorData['timestamp'] === 'string' ? (errorData['timestamp'] as string) : undefined;\n const details =\n typeof errorData['details'] === 'object' ? (errorData['details'] as Record<string, unknown>) : undefined;\n\n throw new NAuthClientError(code, message, {\n statusCode: error.status,\n timestamp,\n details,\n isNetworkError: error.status === 0, // Network error (no response from server)\n });\n }\n\n // Re-throw non-HTTP errors as an SDK error so consumers don't see raw parser crashes.\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new NAuthClientError(NAuthErrorCode.INTERNAL_ERROR, message, {\n statusCode: 0,\n isNetworkError: true,\n });\n }\n }\n}\n","import { Inject, Injectable, Optional } from '@angular/core';\nimport { BehaviorSubject, Observable, Subject } from 'rxjs';\nimport { filter } from 'rxjs/operators';\nimport { NAUTH_CLIENT_CONFIG } from './tokens';\nimport { AngularHttpAdapter } from './http-adapter';\nimport {\n NAuthClient,\n NAuthClientConfig,\n ChallengeResponse,\n AuthResponse,\n TokenResponse,\n AuthUser,\n ConfirmForgotPasswordResponse,\n ForgotPasswordResponse,\n ResetPasswordWithCodeResponse,\n UpdateProfileRequest,\n GetChallengeDataResponse,\n GetSetupDataResponse,\n MFAStatus,\n MFADevice,\n AuthEvent,\n SocialProvider,\n SocialLoginOptions,\n LinkedAccountsResponse,\n SocialVerifyRequest,\n AuditHistoryResponse,\n} from '@nauth-toolkit/client';\n\n/**\n * Angular wrapper around NAuthClient that provides promise-based auth methods and reactive state.\n *\n * This service provides:\n * - Reactive state (currentUser$, isAuthenticated$, challenge$)\n * - All core auth methods as Promises (login, signup, logout, refresh)\n * - Profile management (getProfile, updateProfile, changePassword)\n * - Challenge flow methods (respondToChallenge, resendCode)\n * - MFA management (getMfaStatus, setupMfaDevice, etc.)\n * - Social authentication and account linking\n * - Device trust management\n * - Audit history\n *\n * @example\n * ```typescript\n * constructor(private auth: AuthService) {}\n *\n * // Reactive state\n * this.auth.currentUser$.subscribe(user => ...);\n * this.auth.isAuthenticated$.subscribe(isAuth => ...);\n *\n * // Auth operations with async/await\n * const response = await this.auth.login(email, password);\n *\n * // Profile management\n * await this.auth.changePassword(oldPassword, newPassword);\n * const user = await this.auth.updateProfile({ firstName: 'John' });\n *\n * // MFA operations\n * const status = await this.auth.getMfaStatus();\n * ```\n */\n@Injectable()\nexport class AuthService {\n private readonly client: NAuthClient;\n private readonly config: NAuthClientConfig;\n private readonly currentUserSubject = new BehaviorSubject<AuthUser | null>(null);\n private readonly isAuthenticatedSubject = new BehaviorSubject<boolean>(false);\n private readonly challengeSubject = new BehaviorSubject<AuthResponse | null>(null);\n private readonly authEventsSubject = new Subject<AuthEvent>();\n private initialized = false;\n\n /**\n * @param config - Injected client configuration (required)\n * @param httpAdapter - Angular HTTP adapter for making requests (required)\n */\n constructor(@Inject(NAUTH_CLIENT_CONFIG) config: NAuthClientConfig, httpAdapter: AngularHttpAdapter) {\n this.config = config;\n\n // Use provided httpAdapter (from config or injected)\n const adapter = config.httpAdapter ?? httpAdapter;\n if (!adapter) {\n throw new Error(\n 'HttpAdapter not found. Either provide httpAdapter in NAUTH_CLIENT_CONFIG or ensure HttpClient is available.',\n );\n }\n\n this.client = new NAuthClient({\n ...config,\n httpAdapter: adapter,\n onAuthStateChange: (user) => {\n this.currentUserSubject.next(user);\n this.isAuthenticatedSubject.next(Boolean(user));\n config.onAuthStateChange?.(user);\n },\n });\n\n // Forward all client events to Observable stream\n this.client.on('*', (event) => {\n this.authEventsSubject.next(event);\n });\n\n // Auto-initialize on construction (hydrate from storage)\n this.initialize();\n }\n\n // ============================================================================\n // Reactive State Observables\n // ============================================================================\n\n /**\n * Current user observable.\n */\n get currentUser$(): Observable<AuthUser | null> {\n return this.currentUserSubject.asObservable();\n }\n\n /**\n * Authenticated state observable.\n */\n get isAuthenticated$(): Observable<boolean> {\n return this.isAuthenticatedSubject.asObservable();\n }\n\n /**\n * Current challenge observable (for reactive challenge navigation).\n */\n get challenge$(): Observable<AuthResponse | null> {\n return this.challengeSubject.asObservable();\n }\n\n /**\n * Authentication events stream.\n * Emits all auth lifecycle events for custom logic, analytics, or UI updates.\n */\n get authEvents$(): Observable<AuthEvent> {\n return this.authEventsSubject.asObservable();\n }\n\n /**\n * Successful authentication events stream.\n * Emits when user successfully authenticates (login, signup, social auth).\n */\n get authSuccess$(): Observable<AuthEvent> {\n return this.authEventsSubject.pipe(filter((e) => e.type === 'auth:success'));\n }\n\n /**\n * Authentication error events stream.\n * Emits when authentication fails (login error, OAuth error, etc.).\n */\n get authError$(): Observable<AuthEvent> {\n return this.authEventsSubject.pipe(filter((e) => e.type === 'auth:error' || e.type === 'oauth:error'));\n }\n\n // ============================================================================\n // Sync State Accessors (for guards, templates)\n // ============================================================================\n\n /**\n * Check if authenticated (sync, uses cached state).\n */\n isAuthenticated(): boolean {\n return this.client.isAuthenticatedSync();\n }\n\n /**\n * Get current user (sync, uses cached state).\n */\n getCurrentUser(): AuthUser | null {\n return this.client.getCurrentUser();\n }\n\n /**\n * Get current challenge (sync).\n */\n getCurrentChallenge(): AuthResponse | null {\n return this.challengeSubject.value;\n }\n\n /**\n * Get challenge router for manual navigation control.\n * Useful for guards that need to handle errors or build custom URLs.\n *\n * @returns ChallengeRouter instance\n *\n * @example\n * ```typescript\n * const router = this.auth.getChallengeRouter();\n * await router.navigateToError('oauth');\n * ```\n */\n getChallengeRouter() {\n return this.client.getChallengeRouter();\n }\n\n // ============================================================================\n // Core Auth Methods\n // ============================================================================\n\n /**\n * Login with identifier and password.\n *\n * @param identifier - User email or username\n * @param password - User password\n * @returns Promise with auth response or challenge\n *\n * @example\n * ```typescript\n * const response = await this.auth.login('user@example.com', 'password');\n * if (response.challengeName) {\n * // Handle challenge\n * } else {\n * // Login successful\n * }\n * ```\n */\n async login(identifier: string, password: string): Promise<AuthResponse> {\n const res = await this.client.login(identifier, password);\n return this.updateChallengeState(res);\n }\n\n /**\n * Signup with credentials.\n *\n * @param payload - Signup request payload\n * @returns Promise with auth response or challenge\n *\n * @example\n * ```typescript\n * const response = await this.auth.signup({\n * email: 'new@example.com',\n * password: 'SecurePass123!',\n * firstName: 'John',\n * });\n * ```\n */\n async signup(payload: Parameters<NAuthClient['signup']>[0]): Promise<AuthResponse> {\n const res = await this.client.signup(payload);\n return this.updateChallengeState(res);\n }\n\n /**\n * Logout current session.\n *\n * @param forgetDevice - If true, removes device trust\n *\n * @example\n * ```typescript\n * await this.auth.logout();\n * ```\n */\n async logout(forgetDevice?: boolean): Promise<void> {\n await this.client.logout(forgetDevice);\n this.challengeSubject.next(null);\n // Explicitly update auth state after logout\n this.currentUserSubject.next(null);\n this.isAuthenticatedSubject.next(false);\n\n // Clear CSRF token cookie if in cookies mode\n // Note: Backend should clear httpOnly cookies, but we clear non-httpOnly ones\n if (this.config.tokenDelivery === 'cookies' && typeof document !== 'undefined') {\n const csrfCookieName = this.config.csrf?.cookieName ?? 'nauth_csrf_token';\n // Extract domain from baseUrl if possible\n try {\n const url = new URL(this.config.baseUrl);\n document.cookie = `${csrfCookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=${url.hostname}`;\n // Also try without domain (for localhost)\n document.cookie = `${csrfCookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;\n } catch {\n // Fallback if baseUrl parsing fails\n document.cookie = `${csrfCookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;\n }\n }\n }\n\n /**\n * Logout all sessions.\n *\n * Revokes all active sessions for the current user across all devices.\n * Optionally revokes all trusted devices if forgetDevices is true.\n *\n * @param forgetDevices - If true, also revokes all trusted devices (default: false)\n * @returns Promise with number of sessions revoked\n *\n * @example\n * ```typescript\n * const result = await this.auth.logoutAll();\n * console.log(`Revoked ${result.revokedCount} sessions`);\n * ```\n */\n async logoutAll(forgetDevices?: boolean): Promise<{ revokedCount: number }> {\n const res = await this.client.logoutAll(forgetDevices);\n this.challengeSubject.next(null);\n // Explicitly update auth state after logout\n this.currentUserSubject.next(null);\n this.isAuthenticatedSubject.next(false);\n return res;\n }\n\n /**\n * Refresh tokens.\n *\n * @returns Promise with new tokens\n *\n * @example\n * ```typescript\n * const tokens = await this.auth.refresh();\n * ```\n */\n async refresh(): Promise<TokenResponse> {\n return this.client.refreshTokens();\n }\n\n // ============================================================================\n // Account Recovery (Forgot Password)\n // ============================================================================\n\n /**\n * Request a password reset code (forgot password).\n *\n * @param identifier - User email, username, or phone\n * @returns Promise with password reset response\n *\n * @example\n * ```typescript\n * await this.auth.forgotPassword('user@example.com');\n * ```\n */\n async forgotPassword(identifier: string): Promise<ForgotPasswordResponse> {\n return this.client.forgotPassword(identifier);\n }\n\n /**\n * Confirm a password reset code and set a new password.\n *\n * @param identifier - User email, username, or phone\n * @param code - One-time reset code\n * @param newPassword - New password\n * @returns Promise with confirmation response\n *\n * @example\n * ```typescript\n * await this.auth.confirmForgotPassword('user@example.com', '123456', 'NewPass123!');\n * ```\n */\n async confirmForgotPassword(\n identifier: string,\n code: string,\n newPassword: string,\n ): Promise<ConfirmForgotPasswordResponse> {\n return this.client.confirmForgotPassword(identifier, code, newPassword);\n }\n\n /**\n * Reset password with code or token (generic method for both admin and user-initiated resets).\n *\n * Accepts either:\n * - code: Short numeric code from email/SMS (6-10 digits)\n * - token: Long hex token from reset link (64 chars)\n *\n * @param identifier - User identifier (email, username, phone)\n * @param codeOrToken - Verification code OR token from link\n * @param newPassword - New password\n * @returns Promise with success response\n *\n * @example\n * ```typescript\n * // With code from email\n * await this.auth.resetPasswordWithCode('user@example.com', '123456', 'NewPass123!');\n *\n * // With token from link\n * await this.auth.resetPasswordWithCode('user@example.com', '64-char-token', 'NewPass123!');\n * ```\n */\n async resetPasswordWithCode(\n identifier: string,\n codeOrToken: string,\n newPassword: string,\n ): Promise<ResetPasswordWithCodeResponse> {\n return this.client.resetPasswordWithCode(identifier, codeOrToken, newPassword);\n }\n\n /**\n * Change user password (requires current password).\n *\n * @param oldPassword - Current password\n * @param newPassword - New password (must meet requirements)\n * @returns Promise that resolves when password is changed\n *\n * @example\n * ```typescript\n * await this.auth.changePassword('oldPassword123', 'newSecurePassword456!');\n * ```\n */\n async changePassword(oldPassword: string, newPassword: string): Promise<void> {\n return this.client.changePassword(oldPassword, newPassword);\n }\n\n /**\n * Request password change (must change on next login).\n *\n * @returns Promise that resolves when request is sent\n *\n * @example\n * ```typescript\n * await this.auth.requestPasswordChange();\n * ```\n */\n async requestPasswordChange(): Promise<void> {\n return this.client.requestPasswordChange();\n }\n\n // ============================================================================\n // Profile Management\n // ============================================================================\n\n /**\n * Get current user profile.\n *\n * @returns Promise of current user profile\n *\n * @example\n * ```typescript\n * const user = await this.auth.getProfile();\n * console.log('User profile:', user);\n * ```\n */\n async getProfile(): Promise<AuthUser> {\n const user = await this.client.getProfile();\n // Update local state when profile is fetched\n this.currentUserSubject.next(user);\n return user;\n }\n\n /**\n * Update user profile.\n *\n * @param updates - Profile fields to update\n * @returns Promise of updated user profile\n *\n * @example\n * ```typescript\n * const user = await this.auth.updateProfile({ firstName: 'John', lastName: 'Doe' });\n * console.log('Profile updated:', user);\n * ```\n */\n async updateProfile(updates: UpdateProfileRequest): Promise<AuthUser> {\n const user = await this.client.updateProfile(updates);\n // Update local state when profile is updated\n this.currentUserSubject.next(user);\n return user;\n }\n\n // ============================================================================\n // Challenge Flow Methods (Essential for any auth flow)\n // ============================================================================\n\n /**\n * Respond to a challenge (VERIFY_EMAIL, VERIFY_PHONE, MFA_REQUIRED, etc.).\n *\n * @param response - Challenge response data\n * @returns Promise with auth response or next challenge\n *\n * @example\n * ```typescript\n * const result = await this.auth.respondToChallenge({\n * session: challengeSession,\n * type: 'VERIFY_EMAIL',\n * code: '123456',\n * });\n * ```\n */\n async respondToChallenge(response: ChallengeResponse): Promise<AuthResponse> {\n const res = await this.client.respondToChallenge(response);\n return this.updateChallengeState(res);\n }\n\n /**\n * Resend challenge code.\n *\n * @param session - Challenge session token\n * @returns Promise with destination information\n *\n * @example\n * ```typescript\n * const result = await this.auth.resendCode(session);\n * console.log('Code sent to:', result.destination);\n * ```\n */\n async resendCode(session: string): Promise<{ destination: string }> {\n return this.client.resendCode(session);\n }\n\n /**\n * Get MFA setup data (for MFA_SETUP_REQUIRED challenge).\n *\n * Returns method-specific setup information:\n * - TOTP: { secret, qrCode, manualEntryKey }\n * - SMS: { maskedPhone }\n * - Email: { maskedEmail }\n * - Passkey: WebAuthn registration options\n *\n * @param session - Challenge session token\n * @param method - MFA method to set up\n * @returns Promise of setup data response\n *\n * @example\n * ```typescript\n * const setupData = await this.auth.getSetupData(session, 'totp');\n * console.log('QR Code:', setupData.setupData.qrCode);\n * ```\n */\n async getSetupData(session: string, method: string): Promise<GetSetupDataResponse> {\n return this.client.getSetupData(session, method as Parameters<NAuthClient['getSetupData']>[1]);\n }\n\n /**\n * Get MFA challenge data (for MFA_REQUIRED challenge - e.g., passkey options).\n *\n * @param session - Challenge session token\n * @param method - Challenge method\n * @returns Promise of challenge data response\n *\n * @example\n * ```typescript\n * const challengeData = await this.auth.getChallengeData(session, 'passkey');\n * ```\n */\n async getChallengeData(session: string, method: string): Promise<GetChallengeDataResponse> {\n return this.client.getChallengeData(session, method as Parameters<NAuthClient['getChallengeData']>[1]);\n }\n\n /**\n * Clear stored challenge (when navigating away from challenge flow).\n *\n * @returns Promise that resolves when challenge is cleared\n *\n * @example\n * ```typescript\n * await this.auth.clearChallenge();\n * ```\n */\n async clearChallenge(): Promise<void> {\n await this.client.clearStoredChallenge();\n this.challengeSubject.next(null);\n }\n\n // ============================================================================\n // Social Authentication\n // ============================================================================\n\n /**\n * Initiate social OAuth login flow.\n * Redirects the browser to backend `/auth/social/:provider/redirect`.\n *\n * @param provider - Social provider ('google', 'apple', 'facebook')\n * @param options - Optional redirect options\n * @returns Promise that resolves when redirect starts\n *\n * @example\n * ```typescript\n * await this.auth.loginWithSocial('google', { returnTo: '/auth/callback' });\n * ```\n */\n async loginWithSocial(provider: SocialProvider, options?: SocialLoginOptions): Promise<void> {\n return this.client.loginWithSocial(provider, options);\n }\n\n /**\n * Exchange an exchangeToken (from redirect callback URL) into an AuthResponse.\n *\n * Used for `tokenDelivery: 'json'` or hybrid flows where the backend redirects back\n * with `exchangeToken` instead of setting cookies.\n *\n * @param exchangeToken - One-time exchange token from the callback URL\n * @returns Promise of AuthResponse\n *\n * @example\n * ```typescript\n * const response = await this.auth.exchangeSocialRedirect(exchangeToken);\n * ```\n */\n async exchangeSocialRedirect(exchangeToken: string): Promise<AuthResponse> {\n const res = await this.client.exchangeSocialRedirect(exchangeToken);\n return this.updateChallengeState(res);\n }\n\n /**\n * Verify native social token (mobile).\n *\n * @param request - Social verification request with provider and token\n * @returns Promise of AuthResponse\n *\n * @example\n * ```typescript\n * const result = await this.auth.verifyNativeSocial({\n * provider: 'google',\n * idToken: nativeIdToken,\n * });\n * ```\n */\n async verifyNativeSocial(request: SocialVerifyRequest): Promise<AuthResponse> {\n const res = await this.client.verifyNativeSocial(request);\n return this.updateChallengeState(res);\n }\n\n /**\n * Get linked social accounts.\n *\n * @returns Promise of linked accounts response\n *\n * @example\n * ```typescript\n * const accounts = await this.auth.getLinkedAccounts();\n * console.log('Linked providers:', accounts.providers);\n * ```\n */\n async getLinkedAccounts(): Promise<LinkedAccountsResponse> {\n return this.client.getLinkedAccounts();\n }\n\n /**\n * Link social account.\n *\n * @param provider - Social provider to link\n * @param code - OAuth authorization code\n * @param state - OAuth state parameter\n * @returns Promise with success message\n *\n * @example\n * ```typescript\n * await this.auth.linkSocialAccount('google', code, state);\n * ```\n */\n async linkSocialAccount(provider: string, code: string, state: string): Promise<{ message: string }> {\n return this.client.linkSocialAccount(provider, code, state);\n }\n\n /**\n * Unlink social account.\n *\n * @param provider - Social provider to unlink\n * @returns Promise with success message\n *\n * @example\n * ```typescript\n * await this.auth.unlinkSocialAccount('google');\n * ```\n */\n async unlinkSocialAccount(provider: string): Promise<{ message: string }> {\n return this.client.unlinkSocialAccount(provider);\n }\n\n // ============================================================================\n // MFA Management\n // ============================================================================\n\n /**\n * Get MFA status for the current user.\n *\n * @returns Promise of MFA status\n *\n * @example\n * ```typescript\n * const status = await this.auth.getMfaStatus();\n * console.log('MFA enabled:', status.enabled);\n * ```\n */\n async getMfaStatus(): Promise<MFAStatus> {\n return this.client.getMfaStatus();\n }\n\n /**\n * Get MFA devices for the current user.\n *\n * @returns Promise of MFA devices array\n *\n * @example\n * ```typescript\n * const devices = await this.auth.getMfaDevices();\n * ```\n */\n async getMfaDevices(): Promise<MFADevice[]> {\n return this.client.getMfaDevices() as Promise<MFADevice[]>;\n }\n\n /**\n * Setup MFA device (authenticated user).\n *\n * @param method - MFA method to set up\n * @returns Promise of setup data\n *\n * @example\n * ```typescript\n * const setupData = await this.auth.setupMfaDevice('totp');\n * ```\n */\n async setupMfaDevice(method: string): Promise<unknown> {\n return this.client.setupMfaDevice(method);\n }\n\n /**\n * Verify MFA setup (authenticated user).\n *\n * @param method - MFA method\n * @param setupData - Setup data from setupMfaDevice\n * @param deviceName - Optional device name\n * @returns Promise with device ID\n *\n * @example\n * ```typescript\n * const result = await this.auth.verifyMfaSetup('totp', { code: '123456' }, 'My Phone');\n * ```\n */\n async verifyMfaSetup(\n method: string,\n setupData: Record<string, unknown>,\n deviceName?: string,\n ): Promise<{ deviceId: number }> {\n return this.client.verifyMfaSetup(method, setupData, deviceName);\n }\n\n /**\n * Remove MFA device.\n *\n * @param method - MFA method to remove\n * @returns Promise with success message\n *\n * @example\n * ```typescript\n * await this.auth.removeMfaDevice('sms');\n * ```\n */\n async removeMfaDevice(method: string): Promise<{ message: string }> {\n return this.client.removeMfaDevice(method);\n }\n\n /**\n * Set preferred MFA method.\n *\n * @param method - Device method to set as preferred ('totp', 'sms', 'email', or 'passkey')\n * @returns Promise with success message\n *\n * @example\n * ```typescript\n * await this.auth.setPreferredMfaMethod('totp');\n * ```\n */\n async setPreferredMfaMethod(method: 'totp' | 'sms' | 'email' | 'passkey'): Promise<{ message: string }> {\n return this.client.setPreferredMfaMethod(method);\n }\n\n /**\n * Generate backup codes.\n *\n * @returns Promise of backup codes array\n *\n * @example\n * ```typescript\n * const codes = await this.auth.generateBackupCodes();\n * console.log('Backup codes:', codes);\n * ```\n */\n async generateBackupCodes(): Promise<string[]> {\n return this.client.generateBackupCodes();\n }\n\n /**\n * Set MFA exemption (admin/test scenarios).\n *\n * @param exempt - Whether to exempt user from MFA\n * @param reason - Optional reason for exemption\n * @returns Promise that resolves when exemption is set\n *\n * @example\n * ```typescript\n * await this.auth.setMfaExemption(true, 'Test account');\n * ```\n */\n async setMfaExemption(exempt: boolean, reason?: string): Promise<void> {\n return this.client.setMfaExemption(exempt, reason);\n }\n\n // ============================================================================\n // Device Trust\n // ============================================================================\n\n /**\n * Trust current device.\n *\n * @returns Promise with device token\n *\n * @example\n * ```typescript\n * const result = await this.auth.trustDevice();\n * console.log('Device trusted:', result.deviceToken);\n * ```\n */\n async trustDevice(): Promise<{ deviceToken: string }> {\n return this.client.trustDevice();\n }\n\n /**\n * Check if the current device is trusted.\n *\n * @returns Promise with trusted status\n *\n * @example\n * ```typescript\n * const result = await this.auth.isTrustedDevice();\n * if (result.trusted) {\n * console.log('This device is trusted');\n * }\n * ```\n */\n async isTrustedDevice(): Promise<{ trusted: boolean }> {\n return this.client.isTrustedDevice();\n }\n\n // ============================================================================\n // Audit History\n // ============================================================================\n\n /**\n * Get paginated audit history for the current user.\n *\n * @param params - Query parameters for filtering and pagination\n * @returns Promise of audit history response\n *\n * @example\n * ```typescript\n * const history = await this.auth.getAuditHistory({\n * page: 1,\n * limit: 20,\n * eventType: 'LOGIN_SUCCESS'\n * });\n * console.log('Audit history:', history);\n * ```\n */\n async getAuditHistory(params?: Record<string, string | number | boolean>): Promise<AuditHistoryResponse> {\n return this.client.getAuditHistory(params);\n }\n\n // ============================================================================\n // Escape Hatch\n // ============================================================================\n\n /**\n * Expose underlying NAuthClient for advanced scenarios.\n *\n * @deprecated All core functionality is now exposed directly on AuthService as Promises.\n * Use the direct methods on AuthService instead (e.g., `auth.changePassword()` instead of `auth.getClient().changePassword()`).\n * This method is kept for backward compatibility only and may be removed in a future version.\n *\n * @returns The underlying NAuthClient instance\n *\n * @example\n * ```typescript\n * // Deprecated - use direct methods instead\n * const status = await this.auth.getClient().getMfaStatus();\n *\n * // Preferred - use direct methods\n * const status = await this.auth.getMfaStatus();\n * ```\n */\n getClient(): NAuthClient {\n return this.client;\n }\n\n // ============================================================================\n // Internal Methods\n // ============================================================================\n\n /**\n * Initialize by hydrating state from storage.\n * Called automatically on construction.\n */\n private async initialize(): Promise<void> {\n if (this.initialized) return;\n this.initialized = true;\n\n await this.client.initialize();\n\n // Hydrate challenge state\n const storedChallenge = await this.client.getStoredChallenge();\n if (storedChallenge) {\n this.challengeSubject.next(storedChallenge);\n }\n\n // Update subjects from client state\n const user = this.client.getCurrentUser();\n if (user) {\n this.currentUserSubject.next(user);\n this.isAuthenticatedSubject.next(true);\n }\n }\n\n /**\n * Update challenge state after auth response.\n */\n private updateChallengeState(response: AuthResponse): AuthResponse {\n if (response.challengeName) {\n this.challengeSubject.next(response);\n } else {\n this.challengeSubject.next(null);\n }\n return response;\n }\n}\n","import { Injectable, Inject } from '@angular/core';\nimport {\n HttpInterceptor,\n HttpRequest,\n HttpHandler,\n HttpEvent,\n HttpClient,\n HttpErrorResponse,\n} from '@angular/common/http';\nimport { Router } from '@angular/router';\nimport { Observable, catchError, switchMap, throwError, filter, take, BehaviorSubject, from } from 'rxjs';\nimport { NAUTH_CLIENT_CONFIG } from './tokens';\nimport { AuthService } from './auth.service';\nimport { NAuthClientConfig } from '@nauth-toolkit/client';\n\n/**\n * Refresh state management.\n */\nlet isRefreshing = false;\nconst refreshTokenSubject = new BehaviorSubject<string | null>(null);\nconst retriedRequests = new WeakSet<HttpRequest<unknown>>();\n\n/**\n * Get CSRF token from cookie.\n */\nfunction getCsrfToken(cookieName: string): string | null {\n if (typeof document === 'undefined') return null;\n const match = document.cookie.match(new RegExp(`(^| )${cookieName}=([^;]+)`));\n return match ? decodeURIComponent(match[2]) : null;\n}\n\n/**\n * Class-based HTTP interceptor for NgModule apps (Angular < 17).\n *\n * For standalone components (Angular 17+), use the functional `authInterceptor` instead.\n *\n * @example\n * ```typescript\n * // app.module.ts\n * import { HTTP_INTERCEPTORS } from '@angular/common/http';\n * import { AuthInterceptorClass } from '@nauth-toolkit/client-angular';\n *\n * @NgModule({\n * providers: [\n * { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptorClass, multi: true }\n * ]\n * })\n * ```\n */\n@Injectable()\nexport class AuthInterceptorClass implements HttpInterceptor {\n constructor(\n @Inject(NAUTH_CLIENT_CONFIG) private readonly config: NAuthClientConfig,\n private readonly http: HttpClient,\n private readonly authService: AuthService,\n private readonly router: Router,\n ) {}\n\n intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {\n const tokenDelivery = this.config.tokenDelivery;\n const baseUrl = this.config.baseUrl;\n\n // ============================================================================\n // COOKIES MODE: withCredentials + CSRF token\n // ============================================================================\n if (tokenDelivery === 'cookies') {\n let clonedReq = req.clone({ withCredentials: true });\n\n // Add CSRF token header if it's a mutating request\n if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method)) {\n const csrfToken = getCsrfToken(this.config.csrf?.cookieName || 'XSRF-TOKEN');\n if (csrfToken) {\n clonedReq = clonedReq.clone({\n setHeaders: { [this.config.csrf?.headerName || 'X-XSRF-TOKEN']: csrfToken },\n });\n }\n }\n\n return next.handle(clonedReq).pipe(\n catchError((error: HttpErrorResponse) => {\n if (error.status === 401 && !retriedRequests.has(req)) {\n retriedRequests.add(req);\n\n if (!isRefreshing) {\n isRefreshing = true;\n refreshTokenSubject.next(null);\n\n return from(\n this.http\n .post<{ accessToken?: string }>(`${baseUrl}/refresh`, {}, { withCredentials: true })\n .toPromise(),\n ).pipe(\n switchMap(() => {\n isRefreshing = false;\n refreshTokenSubject.next('refreshed');\n return next.handle(clonedReq);\n }),\n catchError((refreshError) => {\n isRefreshing = false;\n this.authService.logout();\n this.router.navigate([this.config.redirects?.sessionExpired || '/login']);\n return throwError(() => refreshError);\n }),\n );\n } else {\n return refreshTokenSubject.pipe(\n filter((token) => token !== null),\n take(1),\n switchMap(() => next.handle(clonedReq)),\n );\n }\n }\n\n return throwError(() => error);\n }),\n );\n }\n\n // ============================================================================\n // JSON MODE: Delegate to SDK for token handling\n // ============================================================================\n return next.handle(req);\n }\n}\n","import { inject, Inject, Optional } from '@angular/core';\nimport { CanActivateFn, Router, UrlTree } from '@angular/router';\nimport { AuthService } from '../ngmodule/auth.service';\nimport { NAUTH_CLIENT_CONFIG } from '../ngmodule/tokens';\nimport type { NAuthClientConfig } from '@nauth-toolkit/client';\n\n/**\n * Functional route guard for authentication (Angular 17+).\n *\n * Protects routes by checking if user is authenticated.\n * Redirects to configured session expired route (or login) if not authenticated.\n *\n * @param redirectTo - Optional path to redirect to if not authenticated. If not provided, uses `redirects.sessionExpired` from config (defaults to '/login')\n * @returns CanActivateFn guard function\n *\n * @example\n * ```typescript\n * // In route configuration - uses config.redirects.sessionExpired\n * const routes: Routes = [\n * {\n * path: 'home',\n * component: HomeComponent,\n * canActivate: [authGuard()]\n * }\n * ];\n *\n * // Override with custom route\n * const routes: Routes = [\n * {\n * path: 'admin',\n * component: AdminComponent,\n * canActivate: [authGuard('/admin/login')]\n * }\n * ];\n * ```\n */\nexport function authGuard(redirectTo?: string): CanActivateFn {\n return (): boolean | UrlTree => {\n const auth = inject(AuthService);\n const router = inject(Router);\n const config = inject(NAUTH_CLIENT_CONFIG, { optional: true });\n\n if (auth.isAuthenticated()) {\n return true;\n }\n\n // Use provided redirectTo, or config.redirects.sessionExpired, or default to '/login'\n const redirectPath = redirectTo ?? config?.redirects?.sessionExpired ?? '/login';\n\n return router.createUrlTree([redirectPath]);\n };\n}\n\n/**\n * Class-based authentication guard for NgModule compatibility.\n *\n * **Note:** When using `NAuthModule.forRoot()`, `AuthGuard` is automatically provided\n * and has access to the configuration. You don't need to add it to your module's providers.\n *\n * @example\n * ```typescript\n * // app.module.ts - AuthGuard is automatically provided by NAuthModule.forRoot()\n * @NgModule({\n * imports: [\n * NAuthModule.forRoot({\n * baseUrl: 'https://api.example.com/auth',\n * tokenDelivery: 'cookies',\n * redirects: {\n * sessionExpired: '/login?expired=true',\n * },\n * }),\n * RouterModule.forRoot([\n * {\n * path: 'home',\n * component: HomeComponent,\n * canActivate: [AuthGuard], // Uses config.redirects.sessionExpired\n * },\n * ]),\n * ],\n * })\n * export class AppModule {}\n *\n * // Or provide manually in a feature module (still has access to root config)\n * @NgModule({\n * providers: [AuthGuard],\n * })\n * export class FeatureModule {}\n * ```\n */\nexport class AuthGuard {\n /**\n * @param auth - Authentication service\n * @param router - Angular router\n * @param config - Optional client configuration (injected automatically)\n */\n constructor(\n private auth: AuthService,\n private router: Router,\n @Optional() @Inject(NAUTH_CLIENT_CONFIG) private config?: NAuthClientConfig,\n ) {}\n\n /**\n * Check if route can be activated.\n *\n * @returns True if authenticated, otherwise redirects to configured session expired route (or '/login')\n */\n canActivate(): boolean | UrlTree {\n if (this.auth.isAuthenticated()) {\n return true;\n }\n\n // Use config.redirects.sessionExpired or default to '/login'\n const redirectPath = this.config?.redirects?.sessionExpired ?? '/login';\n\n return this.router.createUrlTree([redirectPath]);\n }\n}\n","import { NgModule, ModuleWithProviders } from '@angular/core';\nimport { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';\nimport { NAUTH_CLIENT_CONFIG } from './tokens';\nimport { AuthService } from './auth.service';\nimport { AngularHttpAdapter } from './http-adapter';\nimport { AuthInterceptorClass } from './auth.interceptor.class';\nimport { AuthGuard } from '../lib/auth.guard';\nimport { NAuthClientConfig } from '@nauth-toolkit/client';\n\n/**\n * NgModule for nauth-toolkit Angular integration.\n *\n * Use this for NgModule-based apps (Angular 17+ with NgModule or legacy apps).\n *\n * @example\n * ```typescript\n * // app.module.ts\n * import { NAuthModule } from '@nauth-toolkit/client-angular';\n *\n * @NgModule({\n * imports: [\n * NAuthModule.forRoot({\n * baseUrl: 'http://localhost:3000/auth',\n * tokenDelivery: 'cookies',\n * }),\n * ],\n * })\n * export class AppModule {}\n * ```\n */\n@NgModule({\n imports: [HttpClientModule],\n exports: [HttpClientModule],\n})\nexport class NAuthModule {\n static forRoot(config: NAuthClientConfig): ModuleWithProviders<NAuthModule> {\n return {\n ngModule: NAuthModule,\n providers: [\n {\n provide: NAUTH_CLIENT_CONFIG,\n useValue: config,\n },\n AngularHttpAdapter,\n {\n provide: AuthService,\n useFactory: (httpAdapter: AngularHttpAdapter) => {\n return new AuthService(config, httpAdapter);\n },\n deps: [AngularHttpAdapter],\n },\n {\n provide: HTTP_INTERCEPTORS,\n useClass: AuthInterceptorClass,\n multi: true,\n },\n // Provide AuthGuard so it has access to NAUTH_CLIENT_CONFIG\n AuthGuard,\n ],\n };\n }\n}\n","import { inject, PLATFORM_ID } from '@angular/core';\nimport { isPlatformBrowser } from '@angular/common';\nimport { HttpHandlerFn, HttpInterceptorFn, HttpRequest, HttpClient, HttpErrorResponse } from '@angular/common/http';\nimport { Router } from '@angular/router';\nimport { catchError, switchMap, throwError, filter, take, BehaviorSubject, from } from 'rxjs';\nimport { NAUTH_CLIENT_CONFIG } from '../ngmodule/tokens';\nimport { AuthService } from '../ngmodule/auth.service';\n\n/**\n * Refresh state management.\n * BehaviorSubject pattern is the industry-standard for token refresh.\n */\nlet isRefreshing = false;\nconst refreshTokenSubject = new BehaviorSubject<string | null>(null);\n\n/**\n * Track retried requests to prevent infinite loops.\n */\nconst retriedRequests = new WeakSet<HttpRequest<unknown>>();\n\n/**\n * Get CSRF token from cookie.\n */\nfunction getCsrfToken(cookieName: string): string | null {\n if (typeof document === 'undefined') return null;\n const match = document.cookie.match(new RegExp(`(^| )${cookieName}=([^;]+)`));\n return match ? decodeURIComponent(match[2]) : null;\n}\n\n/**\n * Angular HTTP interceptor for nauth-toolkit.\n *\n * Handles:\n * - Cookies mode: withCredentials + CSRF tokens + refresh via POST\n * - JSON mode: refresh via SDK, retry with new token\n */\nexport const authInterceptor: HttpInterceptorFn = (req: HttpRequest<unknown>, next: HttpHandlerFn) => {\n const config = inject(NAUTH_CLIENT_CONFIG);\n const http = inject(HttpClient);\n const authService = inject(AuthService);\n const platformId = inject(PLATFORM_ID);\n const router = inject(Router);\n const isBrowser = isPlatformBrowser(platformId);\n\n if (!isBrowser) {\n return next(req);\n }\n\n const tokenDelivery = config.tokenDelivery;\n const baseUrl = config.baseUrl;\n const endpoints = config.endpoints ?? {};\n const refreshPath = endpoints.refresh ?? '/refresh';\n const loginPath = endpoints.login ?? '/login';\n const signupPath = endpoints.signup ?? '/signup';\n const socialExchangePath = endpoints.socialExchange ?? '/social/exchange';\n const refreshUrl = `${baseUrl}${refreshPath}`;\n\n const isAuthApiRequest = req.url.includes(baseUrl);\n const isRefreshEndpoint = req.url.includes(refreshPath);\n const isPublicEndpoint =\n req.url.includes(loginPath) || req.url.includes(signupPath) || req.url.includes(socialExchangePath);\n\n // Build request with credentials (cookies mode only)\n let authReq = req;\n if (tokenDelivery === 'cookies') {\n authReq = authReq.clone({ withCredentials: true });\n\n if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method)) {\n const csrfCookieName = config.csrf?.cookieName ?? 'nauth_csrf_token';\n const csrfHeaderName = config.csrf?.headerName ?? 'x-csrf-token';\n const csrfToken = getCsrfToken(csrfCookieName);\n if (csrfToken) {\n authReq = authReq.clone({ setHeaders: { [csrfHeaderName]: csrfToken } });\n }\n }\n }\n\n return next(authReq).pipe(\n catchError((error: unknown) => {\n const shouldHandle =\n error instanceof HttpErrorResponse &&\n error.status === 401 &&\n isAuthApiRequest &&\n !isRefreshEndpoint &&\n !isPublicEndpoint &&\n !retriedRequests.has(req);\n\n if (!shouldHandle) {\n return throwError(() => error);\n }\n\n if (config.debug) {\n console.warn('[nauth-interceptor] 401 detected:', req.url);\n }\n\n if (!isRefreshing) {\n isRefreshing = true;\n refreshTokenSubject.next(null);\n\n if (config.debug) {\n console.warn('[nauth-interceptor] Starting refresh...');\n }\n\n // Refresh based on mode\n const refresh$ =\n tokenDelivery === 'cookies'\n ? http.post<{ accessToken?: string }>(refreshUrl, {}, { withCredentials: true })\n : from(authService.refresh());\n\n return refresh$.pipe(\n switchMap((response) => {\n if (config.debug) {\n console.warn('[nauth-interceptor] Refresh successful');\n }\n isRefreshing = false;\n\n // Get new token (JSON mode) or signal success (cookies mode)\n const newToken = 'accessToken' in response ? response.accessToken : 'success';\n refreshTokenSubject.next(newToken ?? 'success');\n\n // Build retry request\n const retryReq = buildRetryRequest(authReq, tokenDelivery, newToken);\n retriedRequests.add(retryReq);\n\n if (config.debug) {\n console.warn('[nauth-interceptor] Retrying:', req.url);\n }\n return next(retryReq);\n }),\n catchError((err) => {\n if (config.debug) {\n console.error('[nauth-interceptor] Refresh failed:', err);\n }\n isRefreshing = false;\n refreshTokenSubject.next(null);\n\n // Handle session expiration - redirect to configured URL\n if (config.redirects?.sessionExpired) {\n router.navigateByUrl(config.redirects.sessionExpired).catch((navError) => {\n if (config.debug) {\n console.error('[nauth-interceptor] Navigation failed:', navError);\n }\n });\n }\n\n return throwError(() => err);\n }),\n );\n } else {\n // Wait for ongoing refresh\n if (config.debug) {\n console.warn('[nauth-interceptor] Waiting for refresh...');\n }\n return refreshTokenSubject.pipe(\n filter((token): token is string => token !== null),\n take(1),\n switchMap((token) => {\n if (config.debug) {\n console.warn('[nauth-interceptor] Refresh done, retrying:', req.url);\n }\n const retryReq = buildRetryRequest(authReq, tokenDelivery, token);\n retriedRequests.add(retryReq);\n return next(retryReq);\n }),\n );\n }\n }),\n );\n};\n\n/**\n * Build retry request with appropriate auth.\n */\nfunction buildRetryRequest(\n originalReq: HttpRequest<unknown>,\n tokenDelivery: string,\n newToken?: string,\n): HttpRequest<unknown> {\n if (tokenDelivery === 'json' && newToken && newToken !== 'success') {\n return originalReq.clone({\n setHeaders: { Authorization: `Bearer ${newToken}` },\n });\n }\n return originalReq.clone();\n}\n\n/**\n * Class-based interceptor for NgModule compatibility.\n */\nexport class AuthInterceptor {\n intercept(req: HttpRequest<unknown>, next: HttpHandlerFn) {\n return authInterceptor(req, next);\n }\n}\n","import { inject, PLATFORM_ID } from '@angular/core';\nimport { isPlatformBrowser } from '@angular/common';\nimport { type CanActivateFn } from '@angular/router';\nimport { AuthService } from '../ngmodule/auth.service';\nimport { NAUTH_CLIENT_CONFIG } from '../ngmodule/tokens';\nimport { NAuthClientError, NAuthErrorCode } from '@nauth-toolkit/client';\n\n/**\n * Social redirect callback route guard.\n *\n * This guard supports the redirect-first social flow where the backend redirects\n * back to the frontend with:\n * - `appState` (always optional)\n * - `exchangeToken` (present for json/hybrid flows, and for cookie flows that return a challenge)\n * - `error` / `error_description` (provider errors)\n *\n * Behavior:\n * - If `exchangeToken` exists: exchanges it via backend (SDK handles navigation automatically).\n * - If no `exchangeToken`: treat as cookie-success path (SDK handles navigation automatically).\n * - If `error` exists: redirects to oauthError route.\n *\n * @example\n * ```typescript\n * import { socialRedirectCallbackGuard } from '@nauth-toolkit/client/angular';\n *\n * export const routes: Routes = [\n * { path: 'auth/callback', canActivate: [socialRedirectCallbackGuard], component: CallbackComponent },\n * ];\n * ```\n */\nexport const socialRedirectCallbackGuard: CanActivateFn = async (): Promise<boolean> => {\n const auth = inject(AuthService);\n const platformId = inject(PLATFORM_ID);\n const isBrowser = isPlatformBrowser(platformId);\n\n if (!isBrowser) {\n return false;\n }\n\n const params = new URLSearchParams(window.location.search);\n const error = params.get('error');\n const exchangeToken = params.get('exchangeToken');\n const router = auth.getChallengeRouter();\n\n // Provider error: redirect to oauthError\n if (error) {\n await router.navigateToError('oauth');\n return false;\n }\n\n // No exchangeToken: cookie success path; hydrate then navigate to success.\n //\n // Note: we do not \"activate\" the callback route to avoid consumers needing to render a page.\n if (!exchangeToken) {\n // ============================================================================\n // Cookies mode: hydrate user state before redirecting\n // ============================================================================\n // WHY: In cookie delivery, the OAuth callback completes via browser redirects, so the frontend\n // does not receive a JSON AuthResponse to populate the SDK's cached `currentUser`.\n //\n // Without this, sync guards (`authGuard`) can immediately redirect to /login because\n // `currentUser` is still null even though cookies were set successfully.\n try {\n await auth.getProfile();\n await router.navigateToSuccess();\n } catch (err) {\n // Only treat auth failures (401/403) as OAuth errors\n // Network errors or other issues might be temporary - still try success route\n const isAuthError =\n err instanceof NAuthClientError &&\n (err.statusCode === 401 ||\n err.statusCode === 403 ||\n err.code === NAuthErrorCode.AUTH_TOKEN_INVALID ||\n err.code === NAuthErrorCode.AUTH_SESSION_EXPIRED ||\n err.code === NAuthErrorCode.AUTH_SESSION_NOT_FOUND);\n\n if (isAuthError) {\n // Cookies weren't set properly - OAuth failed\n await router.navigateToError('oauth');\n } else {\n // For network errors or other issues, proceed to success route\n // The auth guard will handle authentication state on the next route\n await router.navigateToSuccess();\n }\n }\n return false;\n }\n\n // Exchange token - SDK handles navigation automatically\n await auth.exchangeSocialRedirect(exchangeToken);\n return false;\n};\n","/**\n * Public API Surface of @nauth-toolkit/client-angular (NgModule)\n *\n * This is the default entry point for NgModule-based Angular apps.\n * For standalone components, use: @nauth-toolkit/client-angular/standalone\n */\n\n// Re-export core client types and utilities\nexport * from '@nauth-toolkit/client';\n\n// Export NgModule-specific components (class-based)\nexport * from './ngmodule/tokens';\nexport * from './ngmodule/auth.service';\nexport * from './ngmodule/http-adapter';\nexport * from './ngmodule/auth.interceptor.class';\nexport * from './ngmodule/nauth.module';\n\n// Export functional components (for flexibility in NgModule apps too)\nexport * from './lib/auth.interceptor';\nexport * from './lib/auth.guard';\nexport * from './lib/social-redirect-callback.guard';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.AngularHttpAdapter","isRefreshing","refreshTokenSubject","retriedRequests","getCsrfToken","filter","i2.AuthService"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"nauth-toolkit-client-angular.mjs","sources":["../../src/ngmodule/tokens.ts","../../src/ngmodule/http-adapter.ts","../../src/ngmodule/auth.service.ts","../../src/ngmodule/auth.interceptor.class.ts","../../src/lib/auth.guard.ts","../../src/ngmodule/nauth.module.ts","../../src/lib/auth.interceptor.ts","../../src/lib/social-redirect-callback.guard.ts","../../src/public-api.ts","../../src/nauth-toolkit-client-angular.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport { NAuthClientConfig } from '@nauth-toolkit/client';\n\n/**\n * Injection token for providing NAuthClientConfig in Angular apps.\n */\nexport const NAUTH_CLIENT_CONFIG = new InjectionToken<NAuthClientConfig>('NAUTH_CLIENT_CONFIG');\n","import { Injectable } from '@angular/core';\nimport { HttpClient, HttpErrorResponse } from '@angular/common/http';\nimport { firstValueFrom } from 'rxjs';\nimport { HttpAdapter, HttpRequest, HttpResponse, NAuthClientError, NAuthErrorCode } from '@nauth-toolkit/client';\n\n/**\n * HTTP adapter for Angular using HttpClient.\n *\n * This adapter:\n * - Uses Angular's HttpClient for all requests\n * - Works with Angular's HTTP interceptors (including authInterceptor)\n * - Auto-provided via Angular DI (providedIn: 'root')\n * - Converts HttpClient responses to HttpResponse format\n * - Converts HttpErrorResponse to NAuthClientError\n *\n * Users don't need to configure this manually - it's automatically\n * injected when using AuthService in Angular apps.\n *\n * @example\n * ```typescript\n * // Automatic usage (no manual setup needed)\n * // AuthService automatically injects AngularHttpAdapter\n * constructor(private auth: AuthService) {}\n * ```\n */\n@Injectable()\nexport class AngularHttpAdapter implements HttpAdapter {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Safely parse a JSON response body.\n *\n * Angular's fetch backend (`withFetch()`) will throw a raw `SyntaxError` if\n * `responseType: 'json'` is used and the backend returns HTML (common for\n * proxies, 502 pages, SSR fallbacks, or misrouted requests).\n *\n * To avoid crashing consumer apps, we always request as text and then parse\n * JSON only when the response actually looks like JSON.\n *\n * @param bodyText - Raw response body as text\n * @param contentType - Content-Type header value (if available)\n * @returns Parsed JSON value (unknown)\n * @throws {SyntaxError} When body is non-empty but not valid JSON\n */\n private parseJsonBody(bodyText: string, contentType: string | null): unknown {\n const trimmed = bodyText.trim();\n if (!trimmed) return null;\n\n // If it's clearly HTML, never attempt JSON.parse (some proxies mislabel Content-Type).\n if (trimmed.startsWith('<')) {\n return bodyText;\n }\n\n const looksLikeJson = trimmed.startsWith('{') || trimmed.startsWith('[');\n const isJsonContentType = typeof contentType === 'string' && contentType.toLowerCase().includes('application/json');\n\n if (!looksLikeJson && !isJsonContentType) {\n // Return raw text when it doesn't look like JSON (e.g., HTML error pages).\n return bodyText;\n }\n\n return JSON.parse(trimmed) as unknown;\n }\n\n /**\n * Execute HTTP request using Angular's HttpClient.\n *\n * @param config - Request configuration\n * @returns Response with parsed data\n * @throws NAuthClientError if request fails\n */\n async request<T>(config: HttpRequest): Promise<HttpResponse<T>> {\n try {\n // Use Angular's HttpClient - goes through ALL interceptors.\n // IMPORTANT: Use responseType 'text' to avoid raw JSON.parse crashes when\n // the backend returns HTML (seen in some proxy/SSR/misroute setups).\n const res = await firstValueFrom(\n this.http.request(config.method, config.url, {\n body: config.body,\n headers: config.headers,\n withCredentials: config.credentials === 'include',\n observe: 'response',\n responseType: 'text',\n }),\n );\n\n const contentType = res.headers?.get('content-type');\n const parsed = this.parseJsonBody(res.body ?? '', contentType);\n\n return {\n data: parsed as T,\n status: res.status,\n headers: {}, // Reserved for future header passthrough if needed\n };\n } catch (error) {\n if (error instanceof HttpErrorResponse) {\n // Convert Angular's HttpErrorResponse to NAuthClientError.\n // When using responseType 'text', `error.error` is typically a string.\n const contentType = error.headers?.get('content-type') ?? null;\n const rawBody = typeof error.error === 'string' ? error.error : '';\n const parsedError = this.parseJsonBody(rawBody, contentType);\n\n const errorData =\n typeof parsedError === 'object' && parsedError !== null ? (parsedError as Record<string, unknown>) : {};\n const code =\n typeof errorData['code'] === 'string' ? (errorData['code'] as NAuthErrorCode) : NAuthErrorCode.INTERNAL_ERROR;\n const message =\n typeof errorData['message'] === 'string'\n ? (errorData['message'] as string)\n : typeof parsedError === 'string' && parsedError.trim()\n ? parsedError\n : error.message || `Request failed with status ${error.status}`;\n const timestamp = typeof errorData['timestamp'] === 'string' ? (errorData['timestamp'] as string) : undefined;\n const details =\n typeof errorData['details'] === 'object' ? (errorData['details'] as Record<string, unknown>) : undefined;\n\n throw new NAuthClientError(code, message, {\n statusCode: error.status,\n timestamp,\n details,\n isNetworkError: error.status === 0, // Network error (no response from server)\n });\n }\n\n // Re-throw non-HTTP errors as an SDK error so consumers don't see raw parser crashes.\n const message = error instanceof Error ? error.message : 'Unknown error';\n throw new NAuthClientError(NAuthErrorCode.INTERNAL_ERROR, message, {\n statusCode: 0,\n isNetworkError: true,\n });\n }\n }\n}\n","import { Inject, Injectable, Optional } from '@angular/core';\nimport { BehaviorSubject, Observable, Subject } from 'rxjs';\nimport { filter } from 'rxjs/operators';\nimport { NAUTH_CLIENT_CONFIG } from './tokens';\nimport { AngularHttpAdapter } from './http-adapter';\nimport {\n NAuthClient,\n NAuthClientConfig,\n ChallengeResponse,\n AuthResponse,\n TokenResponse,\n AuthUser,\n ConfirmForgotPasswordResponse,\n ForgotPasswordResponse,\n ResetPasswordWithCodeResponse,\n UpdateProfileRequest,\n GetChallengeDataResponse,\n GetSetupDataResponse,\n MFAStatus,\n MFADevice,\n AuthEvent,\n SocialProvider,\n SocialLoginOptions,\n LinkedAccountsResponse,\n SocialVerifyRequest,\n AuditHistoryResponse,\n} from '@nauth-toolkit/client';\n\n/**\n * Angular wrapper around NAuthClient that provides promise-based auth methods and reactive state.\n *\n * This service provides:\n * - Reactive state (currentUser$, isAuthenticated$, challenge$)\n * - All core auth methods as Promises (login, signup, logout, refresh)\n * - Profile management (getProfile, updateProfile, changePassword)\n * - Challenge flow methods (respondToChallenge, resendCode)\n * - MFA management (getMfaStatus, setupMfaDevice, etc.)\n * - Social authentication and account linking\n * - Device trust management\n * - Audit history\n *\n * @example\n * ```typescript\n * constructor(private auth: AuthService) {}\n *\n * // Reactive state\n * this.auth.currentUser$.subscribe(user => ...);\n * this.auth.isAuthenticated$.subscribe(isAuth => ...);\n *\n * // Auth operations with async/await\n * const response = await this.auth.login(email, password);\n *\n * // Profile management\n * await this.auth.changePassword(oldPassword, newPassword);\n * const user = await this.auth.updateProfile({ firstName: 'John' });\n *\n * // MFA operations\n * const status = await this.auth.getMfaStatus();\n * ```\n */\n@Injectable()\nexport class AuthService {\n private readonly client: NAuthClient;\n private readonly config: NAuthClientConfig;\n private readonly currentUserSubject = new BehaviorSubject<AuthUser | null>(null);\n private readonly isAuthenticatedSubject = new BehaviorSubject<boolean>(false);\n private readonly challengeSubject = new BehaviorSubject<AuthResponse | null>(null);\n private readonly authEventsSubject = new Subject<AuthEvent>();\n private initialized = false;\n\n /**\n * @param config - Injected client configuration (required)\n * @param httpAdapter - Angular HTTP adapter for making requests (required)\n */\n constructor(@Inject(NAUTH_CLIENT_CONFIG) config: NAuthClientConfig, httpAdapter: AngularHttpAdapter) {\n this.config = config;\n\n // Use provided httpAdapter (from config or injected)\n const adapter = config.httpAdapter ?? httpAdapter;\n if (!adapter) {\n throw new Error(\n 'HttpAdapter not found. Either provide httpAdapter in NAUTH_CLIENT_CONFIG or ensure HttpClient is available.',\n );\n }\n\n this.client = new NAuthClient({\n ...config,\n httpAdapter: adapter,\n onAuthStateChange: (user) => {\n this.currentUserSubject.next(user);\n this.isAuthenticatedSubject.next(Boolean(user));\n config.onAuthStateChange?.(user);\n },\n });\n\n // Forward all client events to Observable stream\n this.client.on('*', (event) => {\n this.authEventsSubject.next(event);\n });\n\n // Auto-initialize on construction (hydrate from storage)\n this.initialize();\n }\n\n // ============================================================================\n // Reactive State Observables\n // ============================================================================\n\n /**\n * Current user observable.\n */\n get currentUser$(): Observable<AuthUser | null> {\n return this.currentUserSubject.asObservable();\n }\n\n /**\n * Authenticated state observable.\n */\n get isAuthenticated$(): Observable<boolean> {\n return this.isAuthenticatedSubject.asObservable();\n }\n\n /**\n * Current challenge observable (for reactive challenge navigation).\n */\n get challenge$(): Observable<AuthResponse | null> {\n return this.challengeSubject.asObservable();\n }\n\n /**\n * Authentication events stream.\n * Emits all auth lifecycle events for custom logic, analytics, or UI updates.\n */\n get authEvents$(): Observable<AuthEvent> {\n return this.authEventsSubject.asObservable();\n }\n\n /**\n * Successful authentication events stream.\n * Emits when user successfully authenticates (login, signup, social auth).\n */\n get authSuccess$(): Observable<AuthEvent> {\n return this.authEventsSubject.pipe(filter((e) => e.type === 'auth:success'));\n }\n\n /**\n * Authentication error events stream.\n * Emits when authentication fails (login error, OAuth error, etc.).\n */\n get authError$(): Observable<AuthEvent> {\n return this.authEventsSubject.pipe(filter((e) => e.type === 'auth:error' || e.type === 'oauth:error'));\n }\n\n // ============================================================================\n // Sync State Accessors (for guards, templates)\n // ============================================================================\n\n /**\n * Check if authenticated (sync, uses cached state).\n */\n isAuthenticated(): boolean {\n return this.client.isAuthenticatedSync();\n }\n\n /**\n * Get current user (sync, uses cached state).\n */\n getCurrentUser(): AuthUser | null {\n return this.client.getCurrentUser();\n }\n\n /**\n * Get current challenge (sync).\n */\n getCurrentChallenge(): AuthResponse | null {\n return this.challengeSubject.value;\n }\n\n /**\n * Get challenge router for manual navigation control.\n * Useful for guards that need to handle errors or build custom URLs.\n *\n * @returns ChallengeRouter instance\n *\n * @example\n * ```typescript\n * const router = this.auth.getChallengeRouter();\n * await router.navigateToError('oauth');\n * ```\n */\n getChallengeRouter() {\n return this.client.getChallengeRouter();\n }\n\n // ============================================================================\n // Core Auth Methods\n // ============================================================================\n\n /**\n * Login with identifier and password.\n *\n * @param identifier - User email or username\n * @param password - User password\n * @returns Promise with auth response or challenge\n *\n * @example\n * ```typescript\n * const response = await this.auth.login('user@example.com', 'password');\n * if (response.challengeName) {\n * // Handle challenge\n * } else {\n * // Login successful\n * }\n * ```\n */\n async login(identifier: string, password: string): Promise<AuthResponse> {\n const res = await this.client.login(identifier, password);\n return this.updateChallengeState(res);\n }\n\n /**\n * Signup with credentials.\n *\n * @param payload - Signup request payload\n * @returns Promise with auth response or challenge\n *\n * @example\n * ```typescript\n * const response = await this.auth.signup({\n * email: 'new@example.com',\n * password: 'SecurePass123!',\n * firstName: 'John',\n * });\n * ```\n */\n async signup(payload: Parameters<NAuthClient['signup']>[0]): Promise<AuthResponse> {\n const res = await this.client.signup(payload);\n return this.updateChallengeState(res);\n }\n\n /**\n * Logout current session.\n *\n * @param forgetDevice - If true, removes device trust\n *\n * @example\n * ```typescript\n * await this.auth.logout();\n * ```\n */\n async logout(forgetDevice?: boolean): Promise<void> {\n await this.client.logout(forgetDevice);\n this.challengeSubject.next(null);\n // Explicitly update auth state after logout\n this.currentUserSubject.next(null);\n this.isAuthenticatedSubject.next(false);\n\n // Clear CSRF token cookie if in cookies mode\n // Note: Backend should clear httpOnly cookies, but we clear non-httpOnly ones\n if (this.config.tokenDelivery === 'cookies' && typeof document !== 'undefined') {\n const csrfCookieName = this.config.csrf?.cookieName ?? 'nauth_csrf_token';\n // Extract domain from baseUrl if possible\n try {\n const url = new URL(this.config.baseUrl);\n document.cookie = `${csrfCookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=${url.hostname}`;\n // Also try without domain (for localhost)\n document.cookie = `${csrfCookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;\n } catch {\n // Fallback if baseUrl parsing fails\n document.cookie = `${csrfCookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;\n }\n }\n }\n\n /**\n * Logout all sessions.\n *\n * Revokes all active sessions for the current user across all devices.\n * Optionally revokes all trusted devices if forgetDevices is true.\n *\n * @param forgetDevices - If true, also revokes all trusted devices (default: false)\n * @returns Promise with number of sessions revoked\n *\n * @example\n * ```typescript\n * const result = await this.auth.logoutAll();\n * console.log(`Revoked ${result.revokedCount} sessions`);\n * ```\n */\n async logoutAll(forgetDevices?: boolean): Promise<{ revokedCount: number }> {\n const res = await this.client.logoutAll(forgetDevices);\n this.challengeSubject.next(null);\n // Explicitly update auth state after logout\n this.currentUserSubject.next(null);\n this.isAuthenticatedSubject.next(false);\n return res;\n }\n\n /**\n * Refresh tokens.\n *\n * @returns Promise with new tokens\n *\n * @example\n * ```typescript\n * const tokens = await this.auth.refresh();\n * ```\n */\n async refresh(): Promise<TokenResponse> {\n return this.client.refreshTokens();\n }\n\n // ============================================================================\n // Account Recovery (Forgot Password)\n // ============================================================================\n\n /**\n * Request a password reset code (forgot password).\n *\n * @param identifier - User email, username, or phone\n * @returns Promise with password reset response\n *\n * @example\n * ```typescript\n * await this.auth.forgotPassword('user@example.com');\n * ```\n */\n async forgotPassword(identifier: string): Promise<ForgotPasswordResponse> {\n return this.client.forgotPassword(identifier);\n }\n\n /**\n * Confirm a password reset code and set a new password.\n *\n * @param identifier - User email, username, or phone\n * @param code - One-time reset code\n * @param newPassword - New password\n * @returns Promise with confirmation response\n *\n * @example\n * ```typescript\n * await this.auth.confirmForgotPassword('user@example.com', '123456', 'NewPass123!');\n * ```\n */\n async confirmForgotPassword(\n identifier: string,\n code: string,\n newPassword: string,\n ): Promise<ConfirmForgotPasswordResponse> {\n return this.client.confirmForgotPassword(identifier, code, newPassword);\n }\n\n /**\n * Reset password with code or token (generic method for both admin and user-initiated resets).\n *\n * Accepts either:\n * - code: Short numeric code from email/SMS (6-10 digits)\n * - token: Long hex token from reset link (64 chars)\n *\n * @param identifier - User identifier (email, username, phone)\n * @param codeOrToken - Verification code OR token from link\n * @param newPassword - New password\n * @returns Promise with success response\n *\n * @example\n * ```typescript\n * // With code from email\n * await this.auth.resetPasswordWithCode('user@example.com', '123456', 'NewPass123!');\n *\n * // With token from link\n * await this.auth.resetPasswordWithCode('user@example.com', '64-char-token', 'NewPass123!');\n * ```\n */\n async resetPasswordWithCode(\n identifier: string,\n codeOrToken: string,\n newPassword: string,\n ): Promise<ResetPasswordWithCodeResponse> {\n return this.client.resetPasswordWithCode(identifier, codeOrToken, newPassword);\n }\n\n /**\n * Change user password (requires current password).\n *\n * @param oldPassword - Current password\n * @param newPassword - New password (must meet requirements)\n * @returns Promise that resolves when password is changed\n *\n * @example\n * ```typescript\n * await this.auth.changePassword('oldPassword123', 'newSecurePassword456!');\n * ```\n */\n async changePassword(oldPassword: string, newPassword: string): Promise<void> {\n return this.client.changePassword(oldPassword, newPassword);\n }\n\n /**\n * Request password change (must change on next login).\n *\n * @returns Promise that resolves when request is sent\n *\n * @example\n * ```typescript\n * await this.auth.requestPasswordChange();\n * ```\n */\n async requestPasswordChange(): Promise<void> {\n return this.client.requestPasswordChange();\n }\n\n // ============================================================================\n // Profile Management\n // ============================================================================\n\n /**\n * Get current user profile.\n *\n * @returns Promise of current user profile\n *\n * @example\n * ```typescript\n * const user = await this.auth.getProfile();\n * console.log('User profile:', user);\n * ```\n */\n async getProfile(): Promise<AuthUser> {\n const user = await this.client.getProfile();\n // Update local state when profile is fetched\n this.currentUserSubject.next(user);\n return user;\n }\n\n /**\n * Update user profile.\n *\n * @param updates - Profile fields to update\n * @returns Promise of updated user profile\n *\n * @example\n * ```typescript\n * const user = await this.auth.updateProfile({ firstName: 'John', lastName: 'Doe' });\n * console.log('Profile updated:', user);\n * ```\n */\n async updateProfile(updates: UpdateProfileRequest): Promise<AuthUser> {\n const user = await this.client.updateProfile(updates);\n // Update local state when profile is updated\n this.currentUserSubject.next(user);\n return user;\n }\n\n // ============================================================================\n // Challenge Flow Methods (Essential for any auth flow)\n // ============================================================================\n\n /**\n * Respond to a challenge (VERIFY_EMAIL, VERIFY_PHONE, MFA_REQUIRED, etc.).\n *\n * @param response - Challenge response data\n * @returns Promise with auth response or next challenge\n *\n * @example\n * ```typescript\n * const result = await this.auth.respondToChallenge({\n * session: challengeSession,\n * type: 'VERIFY_EMAIL',\n * code: '123456',\n * });\n * ```\n */\n async respondToChallenge(response: ChallengeResponse): Promise<AuthResponse> {\n const res = await this.client.respondToChallenge(response);\n return this.updateChallengeState(res);\n }\n\n /**\n * Resend challenge code.\n *\n * @param session - Challenge session token\n * @returns Promise with destination information\n *\n * @example\n * ```typescript\n * const result = await this.auth.resendCode(session);\n * console.log('Code sent to:', result.destination);\n * ```\n */\n async resendCode(session: string): Promise<{ destination: string }> {\n return this.client.resendCode(session);\n }\n\n /**\n * Get MFA setup data (for MFA_SETUP_REQUIRED challenge).\n *\n * Returns method-specific setup information:\n * - TOTP: { secret, qrCode, manualEntryKey }\n * - SMS: { maskedPhone }\n * - Email: { maskedEmail }\n * - Passkey: WebAuthn registration options\n *\n * @param session - Challenge session token\n * @param method - MFA method to set up\n * @returns Promise of setup data response\n *\n * @example\n * ```typescript\n * const setupData = await this.auth.getSetupData(session, 'totp');\n * console.log('QR Code:', setupData.setupData.qrCode);\n * ```\n */\n async getSetupData(session: string, method: string): Promise<GetSetupDataResponse> {\n return this.client.getSetupData(session, method as Parameters<NAuthClient['getSetupData']>[1]);\n }\n\n /**\n * Get MFA challenge data (for MFA_REQUIRED challenge - e.g., passkey options).\n *\n * @param session - Challenge session token\n * @param method - Challenge method\n * @returns Promise of challenge data response\n *\n * @example\n * ```typescript\n * const challengeData = await this.auth.getChallengeData(session, 'passkey');\n * ```\n */\n async getChallengeData(session: string, method: string): Promise<GetChallengeDataResponse> {\n return this.client.getChallengeData(session, method as Parameters<NAuthClient['getChallengeData']>[1]);\n }\n\n /**\n * Clear stored challenge (when navigating away from challenge flow).\n *\n * @returns Promise that resolves when challenge is cleared\n *\n * @example\n * ```typescript\n * await this.auth.clearChallenge();\n * ```\n */\n async clearChallenge(): Promise<void> {\n await this.client.clearStoredChallenge();\n this.challengeSubject.next(null);\n }\n\n // ============================================================================\n // Social Authentication\n // ============================================================================\n\n /**\n * Initiate social OAuth login flow.\n * Redirects the browser to backend `/auth/social/:provider/redirect`.\n *\n * @param provider - Social provider ('google', 'apple', 'facebook')\n * @param options - Optional redirect options\n * @returns Promise that resolves when redirect starts\n *\n * @example\n * ```typescript\n * await this.auth.loginWithSocial('google', { returnTo: '/auth/callback' });\n * ```\n */\n async loginWithSocial(provider: SocialProvider, options?: SocialLoginOptions): Promise<void> {\n return this.client.loginWithSocial(provider, options);\n }\n\n /**\n * Exchange an exchangeToken (from redirect callback URL) into an AuthResponse.\n *\n * Used for `tokenDelivery: 'json'` or hybrid flows where the backend redirects back\n * with `exchangeToken` instead of setting cookies.\n *\n * @param exchangeToken - One-time exchange token from the callback URL\n * @returns Promise of AuthResponse\n *\n * @example\n * ```typescript\n * const response = await this.auth.exchangeSocialRedirect(exchangeToken);\n * ```\n */\n async exchangeSocialRedirect(exchangeToken: string): Promise<AuthResponse> {\n const res = await this.client.exchangeSocialRedirect(exchangeToken);\n return this.updateChallengeState(res);\n }\n\n /**\n * Verify native social token (mobile).\n *\n * @param request - Social verification request with provider and token\n * @returns Promise of AuthResponse\n *\n * @example\n * ```typescript\n * const result = await this.auth.verifyNativeSocial({\n * provider: 'google',\n * idToken: nativeIdToken,\n * });\n * ```\n */\n async verifyNativeSocial(request: SocialVerifyRequest): Promise<AuthResponse> {\n const res = await this.client.verifyNativeSocial(request);\n return this.updateChallengeState(res);\n }\n\n /**\n * Get linked social accounts.\n *\n * @returns Promise of linked accounts response\n *\n * @example\n * ```typescript\n * const accounts = await this.auth.getLinkedAccounts();\n * console.log('Linked providers:', accounts.providers);\n * ```\n */\n async getLinkedAccounts(): Promise<LinkedAccountsResponse> {\n return this.client.getLinkedAccounts();\n }\n\n /**\n * Link social account.\n *\n * @param provider - Social provider to link\n * @param code - OAuth authorization code\n * @param state - OAuth state parameter\n * @returns Promise with success message\n *\n * @example\n * ```typescript\n * await this.auth.linkSocialAccount('google', code, state);\n * ```\n */\n async linkSocialAccount(provider: string, code: string, state: string): Promise<{ message: string }> {\n return this.client.linkSocialAccount(provider, code, state);\n }\n\n /**\n * Unlink social account.\n *\n * @param provider - Social provider to unlink\n * @returns Promise with success message\n *\n * @example\n * ```typescript\n * await this.auth.unlinkSocialAccount('google');\n * ```\n */\n async unlinkSocialAccount(provider: string): Promise<{ message: string }> {\n return this.client.unlinkSocialAccount(provider);\n }\n\n // ============================================================================\n // MFA Management\n // ============================================================================\n\n /**\n * Get MFA status for the current user.\n *\n * @returns Promise of MFA status\n *\n * @example\n * ```typescript\n * const status = await this.auth.getMfaStatus();\n * console.log('MFA enabled:', status.enabled);\n * ```\n */\n async getMfaStatus(): Promise<MFAStatus> {\n return this.client.getMfaStatus();\n }\n\n /**\n * Get MFA devices for the current user.\n *\n * @returns Promise of MFA devices array\n *\n * @example\n * ```typescript\n * const devices = await this.auth.getMfaDevices();\n * ```\n */\n async getMfaDevices(): Promise<MFADevice[]> {\n return this.client.getMfaDevices() as Promise<MFADevice[]>;\n }\n\n /**\n * Setup MFA device (authenticated user).\n *\n * @param method - MFA method to set up\n * @returns Promise of setup data\n *\n * @example\n * ```typescript\n * const setupData = await this.auth.setupMfaDevice('totp');\n * ```\n */\n async setupMfaDevice(method: string): Promise<unknown> {\n return this.client.setupMfaDevice(method);\n }\n\n /**\n * Verify MFA setup (authenticated user).\n *\n * @param method - MFA method\n * @param setupData - Setup data from setupMfaDevice\n * @param deviceName - Optional device name\n * @returns Promise with device ID\n *\n * @example\n * ```typescript\n * const result = await this.auth.verifyMfaSetup('totp', { code: '123456' }, 'My Phone');\n * ```\n */\n async verifyMfaSetup(\n method: string,\n setupData: Record<string, unknown>,\n deviceName?: string,\n ): Promise<{ deviceId: number }> {\n return this.client.verifyMfaSetup(method, setupData, deviceName);\n }\n\n /**\n * Remove MFA device.\n *\n * @param method - MFA method to remove\n * @returns Promise with success message\n *\n * @example\n * ```typescript\n * await this.auth.removeMfaDevice('sms');\n * ```\n */\n async removeMfaDevice(method: string): Promise<{ message: string }> {\n return this.client.removeMfaDevice(method);\n }\n\n /**\n * Set preferred MFA method.\n *\n * @param method - Device method to set as preferred ('totp', 'sms', 'email', or 'passkey')\n * @returns Promise with success message\n *\n * @example\n * ```typescript\n * await this.auth.setPreferredMfaMethod('totp');\n * ```\n */\n async setPreferredMfaMethod(method: 'totp' | 'sms' | 'email' | 'passkey'): Promise<{ message: string }> {\n return this.client.setPreferredMfaMethod(method);\n }\n\n /**\n * Generate backup codes.\n *\n * @returns Promise of backup codes array\n *\n * @example\n * ```typescript\n * const codes = await this.auth.generateBackupCodes();\n * console.log('Backup codes:', codes);\n * ```\n */\n async generateBackupCodes(): Promise<string[]> {\n return this.client.generateBackupCodes();\n }\n\n /**\n * Set MFA exemption (admin/test scenarios).\n *\n * @param exempt - Whether to exempt user from MFA\n * @param reason - Optional reason for exemption\n * @returns Promise that resolves when exemption is set\n *\n * @example\n * ```typescript\n * await this.auth.setMfaExemption(true, 'Test account');\n * ```\n */\n async setMfaExemption(exempt: boolean, reason?: string): Promise<void> {\n return this.client.setMfaExemption(exempt, reason);\n }\n\n // ============================================================================\n // Device Trust\n // ============================================================================\n\n /**\n * Trust current device.\n *\n * @returns Promise with device token\n *\n * @example\n * ```typescript\n * const result = await this.auth.trustDevice();\n * console.log('Device trusted:', result.deviceToken);\n * ```\n */\n async trustDevice(): Promise<{ deviceToken: string }> {\n return this.client.trustDevice();\n }\n\n /**\n * Check if the current device is trusted.\n *\n * @returns Promise with trusted status\n *\n * @example\n * ```typescript\n * const result = await this.auth.isTrustedDevice();\n * if (result.trusted) {\n * console.log('This device is trusted');\n * }\n * ```\n */\n async isTrustedDevice(): Promise<{ trusted: boolean }> {\n return this.client.isTrustedDevice();\n }\n\n // ============================================================================\n // Audit History\n // ============================================================================\n\n /**\n * Get paginated audit history for the current user.\n *\n * @param params - Query parameters for filtering and pagination\n * @returns Promise of audit history response\n *\n * @example\n * ```typescript\n * const history = await this.auth.getAuditHistory({\n * page: 1,\n * limit: 20,\n * eventType: 'LOGIN_SUCCESS'\n * });\n * console.log('Audit history:', history);\n * ```\n */\n async getAuditHistory(params?: Record<string, string | number | boolean>): Promise<AuditHistoryResponse> {\n return this.client.getAuditHistory(params);\n }\n\n // ============================================================================\n // Escape Hatch\n // ============================================================================\n\n /**\n * Expose underlying NAuthClient for advanced scenarios.\n *\n * @deprecated All core functionality is now exposed directly on AuthService as Promises.\n * Use the direct methods on AuthService instead (e.g., `auth.changePassword()` instead of `auth.getClient().changePassword()`).\n * This method is kept for backward compatibility only and may be removed in a future version.\n *\n * @returns The underlying NAuthClient instance\n *\n * @example\n * ```typescript\n * // Deprecated - use direct methods instead\n * const status = await this.auth.getClient().getMfaStatus();\n *\n * // Preferred - use direct methods\n * const status = await this.auth.getMfaStatus();\n * ```\n */\n getClient(): NAuthClient {\n return this.client;\n }\n\n // ============================================================================\n // Internal Methods\n // ============================================================================\n\n /**\n * Initialize by hydrating state from storage.\n * Called automatically on construction.\n */\n private async initialize(): Promise<void> {\n if (this.initialized) return;\n this.initialized = true;\n\n await this.client.initialize();\n\n // Hydrate challenge state\n const storedChallenge = await this.client.getStoredChallenge();\n if (storedChallenge) {\n this.challengeSubject.next(storedChallenge);\n }\n\n // Update subjects from client state\n const user = this.client.getCurrentUser();\n if (user) {\n this.currentUserSubject.next(user);\n this.isAuthenticatedSubject.next(true);\n }\n }\n\n /**\n * Update challenge state after auth response.\n */\n private updateChallengeState(response: AuthResponse): AuthResponse {\n if (response.challengeName) {\n this.challengeSubject.next(response);\n } else {\n this.challengeSubject.next(null);\n }\n return response;\n }\n}\n","import { Injectable, Inject } from '@angular/core';\nimport {\n HttpInterceptor,\n HttpRequest,\n HttpHandler,\n HttpEvent,\n HttpClient,\n HttpErrorResponse,\n} from '@angular/common/http';\nimport { Router } from '@angular/router';\nimport { Observable, catchError, switchMap, throwError, filter, take, BehaviorSubject, from } from 'rxjs';\nimport { NAUTH_CLIENT_CONFIG } from './tokens';\nimport { AuthService } from './auth.service';\nimport { NAuthClientConfig } from '@nauth-toolkit/client';\n\n/**\n * Refresh state management.\n */\nlet isRefreshing = false;\nconst refreshTokenSubject = new BehaviorSubject<string | null>(null);\nconst retriedRequests = new WeakSet<HttpRequest<unknown>>();\n\n/**\n * Get CSRF token from cookie.\n */\nfunction getCsrfToken(cookieName: string): string | null {\n if (typeof document === 'undefined') return null;\n const match = document.cookie.match(new RegExp(`(^| )${cookieName}=([^;]+)`));\n return match ? decodeURIComponent(match[2]) : null;\n}\n\n/**\n * Class-based HTTP interceptor for NgModule apps (Angular < 17).\n *\n * For standalone components (Angular 17+), use the functional `authInterceptor` instead.\n *\n * @example\n * ```typescript\n * // app.module.ts\n * import { HTTP_INTERCEPTORS } from '@angular/common/http';\n * import { AuthInterceptorClass } from '@nauth-toolkit/client-angular';\n *\n * @NgModule({\n * providers: [\n * { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptorClass, multi: true }\n * ]\n * })\n * ```\n */\n@Injectable()\nexport class AuthInterceptorClass implements HttpInterceptor {\n constructor(\n @Inject(NAUTH_CLIENT_CONFIG) private readonly config: NAuthClientConfig,\n private readonly http: HttpClient,\n private readonly authService: AuthService,\n private readonly router: Router,\n ) {}\n\n intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {\n const tokenDelivery = this.config.tokenDelivery;\n const baseUrl = this.config.baseUrl;\n\n // ============================================================================\n // COOKIES MODE: withCredentials + CSRF token\n // ============================================================================\n if (tokenDelivery === 'cookies') {\n let clonedReq = req.clone({ withCredentials: true });\n\n // Add CSRF token header if it's a mutating request\n if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method)) {\n const csrfToken = getCsrfToken(this.config.csrf?.cookieName || 'XSRF-TOKEN');\n if (csrfToken) {\n clonedReq = clonedReq.clone({\n setHeaders: { [this.config.csrf?.headerName || 'X-XSRF-TOKEN']: csrfToken },\n });\n }\n }\n\n return next.handle(clonedReq).pipe(\n catchError((error: HttpErrorResponse) => {\n if (error.status === 401 && !retriedRequests.has(req)) {\n retriedRequests.add(req);\n\n if (!isRefreshing) {\n isRefreshing = true;\n refreshTokenSubject.next(null);\n\n return from(\n this.http\n .post<{ accessToken?: string }>(`${baseUrl}/refresh`, {}, { withCredentials: true })\n .toPromise(),\n ).pipe(\n switchMap(() => {\n isRefreshing = false;\n refreshTokenSubject.next('refreshed');\n return next.handle(clonedReq);\n }),\n catchError((refreshError) => {\n isRefreshing = false;\n this.authService.logout();\n this.router.navigate([this.config.redirects?.sessionExpired || '/login']);\n return throwError(() => refreshError);\n }),\n );\n } else {\n return refreshTokenSubject.pipe(\n filter((token) => token !== null),\n take(1),\n switchMap(() => next.handle(clonedReq)),\n );\n }\n }\n\n return throwError(() => error);\n }),\n );\n }\n\n // ============================================================================\n // JSON MODE: Delegate to SDK for token handling\n // ============================================================================\n return next.handle(req);\n }\n}\n","import { inject, Inject, Optional } from '@angular/core';\nimport { CanActivateFn, Router, UrlTree } from '@angular/router';\nimport { AuthService } from '../ngmodule/auth.service';\nimport { NAUTH_CLIENT_CONFIG } from '../ngmodule/tokens';\nimport type { NAuthClientConfig } from '@nauth-toolkit/client';\n\n/**\n * Functional route guard for authentication (Angular 17+).\n *\n * Protects routes by checking if user is authenticated.\n * Redirects to configured session expired route (or login) if not authenticated.\n *\n * @param redirectTo - Optional path to redirect to if not authenticated. If not provided, uses `redirects.sessionExpired` from config (defaults to '/login')\n * @returns CanActivateFn guard function\n *\n * @example\n * ```typescript\n * // In route configuration - uses config.redirects.sessionExpired\n * const routes: Routes = [\n * {\n * path: 'home',\n * component: HomeComponent,\n * canActivate: [authGuard()]\n * }\n * ];\n *\n * // Override with custom route\n * const routes: Routes = [\n * {\n * path: 'admin',\n * component: AdminComponent,\n * canActivate: [authGuard('/admin/login')]\n * }\n * ];\n * ```\n */\nexport function authGuard(redirectTo?: string): CanActivateFn {\n return (): boolean | UrlTree => {\n const auth = inject(AuthService);\n const router = inject(Router);\n const config = inject(NAUTH_CLIENT_CONFIG, { optional: true });\n\n if (auth.isAuthenticated()) {\n return true;\n }\n\n // Use provided redirectTo, or config.redirects.sessionExpired, or default to '/login'\n const redirectPath = redirectTo ?? config?.redirects?.sessionExpired ?? '/login';\n\n return router.createUrlTree([redirectPath]);\n };\n}\n\n/**\n * Class-based authentication guard for NgModule compatibility.\n *\n * **Note:** When using `NAuthModule.forRoot()`, `AuthGuard` is automatically provided\n * and has access to the configuration. You don't need to add it to your module's providers.\n *\n * @example\n * ```typescript\n * // app.module.ts - AuthGuard is automatically provided by NAuthModule.forRoot()\n * @NgModule({\n * imports: [\n * NAuthModule.forRoot({\n * baseUrl: 'https://api.example.com/auth',\n * tokenDelivery: 'cookies',\n * redirects: {\n * sessionExpired: '/login?expired=true',\n * },\n * }),\n * RouterModule.forRoot([\n * {\n * path: 'home',\n * component: HomeComponent,\n * canActivate: [AuthGuard], // Uses config.redirects.sessionExpired\n * },\n * ]),\n * ],\n * })\n * export class AppModule {}\n *\n * // Or provide manually in a feature module (still has access to root config)\n * @NgModule({\n * providers: [AuthGuard],\n * })\n * export class FeatureModule {}\n * ```\n */\nexport class AuthGuard {\n /**\n * @param auth - Authentication service\n * @param router - Angular router\n * @param config - Optional client configuration (injected automatically)\n */\n constructor(\n private auth: AuthService,\n private router: Router,\n @Optional() @Inject(NAUTH_CLIENT_CONFIG) private config?: NAuthClientConfig,\n ) {}\n\n /**\n * Check if route can be activated.\n *\n * @returns True if authenticated, otherwise redirects to configured session expired route (or '/login')\n */\n canActivate(): boolean | UrlTree {\n if (this.auth.isAuthenticated()) {\n return true;\n }\n\n // Use config.redirects.sessionExpired or default to '/login'\n const redirectPath = this.config?.redirects?.sessionExpired ?? '/login';\n\n return this.router.createUrlTree([redirectPath]);\n }\n}\n","import { NgModule, ModuleWithProviders } from '@angular/core';\nimport { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';\nimport { NAUTH_CLIENT_CONFIG } from './tokens';\nimport { AuthService } from './auth.service';\nimport { AngularHttpAdapter } from './http-adapter';\nimport { AuthInterceptorClass } from './auth.interceptor.class';\nimport { AuthGuard } from '../lib/auth.guard';\nimport { NAuthClientConfig } from '@nauth-toolkit/client';\n\n/**\n * NgModule for nauth-toolkit Angular integration.\n *\n * Use this for NgModule-based apps (Angular 17+ with NgModule or legacy apps).\n *\n * @example\n * ```typescript\n * // app.module.ts\n * import { NAuthModule } from '@nauth-toolkit/client-angular';\n *\n * @NgModule({\n * imports: [\n * NAuthModule.forRoot({\n * baseUrl: 'http://localhost:3000/auth',\n * tokenDelivery: 'cookies',\n * }),\n * ],\n * })\n * export class AppModule {}\n * ```\n */\n@NgModule({\n imports: [HttpClientModule],\n exports: [HttpClientModule],\n})\nexport class NAuthModule {\n static forRoot(config: NAuthClientConfig): ModuleWithProviders<NAuthModule> {\n return {\n ngModule: NAuthModule,\n providers: [\n {\n provide: NAUTH_CLIENT_CONFIG,\n useValue: config,\n },\n AngularHttpAdapter,\n {\n provide: AuthService,\n useFactory: (httpAdapter: AngularHttpAdapter) => {\n return new AuthService(config, httpAdapter);\n },\n deps: [AngularHttpAdapter],\n },\n {\n provide: HTTP_INTERCEPTORS,\n useClass: AuthInterceptorClass,\n multi: true,\n },\n // Provide AuthGuard so it has access to NAUTH_CLIENT_CONFIG\n AuthGuard,\n ],\n };\n }\n}\n","import { inject, PLATFORM_ID } from '@angular/core';\nimport { isPlatformBrowser } from '@angular/common';\nimport { HttpHandlerFn, HttpInterceptorFn, HttpRequest, HttpClient, HttpErrorResponse } from '@angular/common/http';\nimport { Router } from '@angular/router';\nimport { catchError, switchMap, throwError, filter, take, BehaviorSubject, from } from 'rxjs';\nimport { NAUTH_CLIENT_CONFIG } from '../ngmodule/tokens';\nimport { AuthService } from '../ngmodule/auth.service';\n\n/**\n * Refresh state management.\n * BehaviorSubject pattern is the industry-standard for token refresh.\n */\nlet isRefreshing = false;\nconst refreshTokenSubject = new BehaviorSubject<string | null>(null);\n\n/**\n * Track retried requests to prevent infinite loops.\n */\nconst retriedRequests = new WeakSet<HttpRequest<unknown>>();\n\n/**\n * Get CSRF token from cookie.\n */\nfunction getCsrfToken(cookieName: string): string | null {\n if (typeof document === 'undefined') return null;\n const match = document.cookie.match(new RegExp(`(^| )${cookieName}=([^;]+)`));\n return match ? decodeURIComponent(match[2]) : null;\n}\n\n/**\n * Angular HTTP interceptor for nauth-toolkit.\n *\n * Handles:\n * - Cookies mode: withCredentials + CSRF tokens + refresh via POST\n * - JSON mode: refresh via SDK, retry with new token\n */\nexport const authInterceptor: HttpInterceptorFn = (req: HttpRequest<unknown>, next: HttpHandlerFn) => {\n const config = inject(NAUTH_CLIENT_CONFIG);\n const http = inject(HttpClient);\n const authService = inject(AuthService);\n const platformId = inject(PLATFORM_ID);\n const router = inject(Router);\n const isBrowser = isPlatformBrowser(platformId);\n\n if (!isBrowser) {\n return next(req);\n }\n\n // #region agent log\n if (req.url.includes('/profile') && req.method === 'PUT') {\n fetch('http://127.0.0.1:7242/ingest/97f9fe53-6a8b-43e2-ae9b-4b2d0f725816', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n location: 'auth.interceptor.ts:entry',\n message: 'Original request entry',\n data: { reqBody: req.body, reqBodyType: typeof req.body, reqMethod: req.method, reqUrl: req.url },\n timestamp: Date.now(),\n sessionId: 'debug-session',\n hypothesisId: 'A',\n }),\n }).catch(() => {});\n }\n // #endregion\n\n const tokenDelivery = config.tokenDelivery;\n const baseUrl = config.baseUrl;\n const endpoints = config.endpoints ?? {};\n const refreshPath = endpoints.refresh ?? '/refresh';\n const loginPath = endpoints.login ?? '/login';\n const signupPath = endpoints.signup ?? '/signup';\n const socialExchangePath = endpoints.socialExchange ?? '/social/exchange';\n const refreshUrl = `${baseUrl}${refreshPath}`;\n\n const isAuthApiRequest = req.url.includes(baseUrl);\n const isRefreshEndpoint = req.url.includes(refreshPath);\n const isPublicEndpoint =\n req.url.includes(loginPath) || req.url.includes(signupPath) || req.url.includes(socialExchangePath);\n\n // Build request with credentials (cookies mode only)\n let authReq = req;\n if (tokenDelivery === 'cookies') {\n authReq = authReq.clone({ withCredentials: true });\n\n if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method)) {\n const csrfCookieName = config.csrf?.cookieName ?? 'nauth_csrf_token';\n const csrfHeaderName = config.csrf?.headerName ?? 'x-csrf-token';\n const csrfToken = getCsrfToken(csrfCookieName);\n if (csrfToken) {\n authReq = authReq.clone({ setHeaders: { [csrfHeaderName]: csrfToken } });\n }\n }\n }\n\n return next(authReq).pipe(\n catchError((error: unknown) => {\n const shouldHandle =\n error instanceof HttpErrorResponse &&\n error.status === 401 &&\n isAuthApiRequest &&\n !isRefreshEndpoint &&\n !isPublicEndpoint &&\n !retriedRequests.has(req);\n\n if (!shouldHandle) {\n return throwError(() => error);\n }\n\n // Mark original request as retried to prevent infinite loops\n retriedRequests.add(req);\n\n if (config.debug) {\n console.warn('[nauth-interceptor] 401 detected:', req.url);\n }\n\n if (!isRefreshing) {\n isRefreshing = true;\n refreshTokenSubject.next(null);\n\n if (config.debug) {\n console.warn('[nauth-interceptor] Starting refresh...');\n }\n\n // Refresh based on mode\n const refresh$ =\n tokenDelivery === 'cookies'\n ? http.post<{ accessToken?: string }>(refreshUrl, {}, { withCredentials: true })\n : from(authService.refresh());\n\n return refresh$.pipe(\n switchMap((response) => {\n if (config.debug) {\n console.warn('[nauth-interceptor] Refresh successful');\n }\n isRefreshing = false;\n\n // Get new token (JSON mode) or signal success (cookies mode)\n const newToken = 'accessToken' in response ? response.accessToken : 'success';\n refreshTokenSubject.next(newToken ?? 'success');\n\n // #region agent log\n fetch('http://127.0.0.1:7242/ingest/97f9fe53-6a8b-43e2-ae9b-4b2d0f725816', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n location: 'auth.interceptor.ts:125',\n message: 'Before buildRetryRequest',\n data: {\n authReqBody: authReq.body,\n authReqMethod: authReq.method,\n authReqUrl: authReq.url,\n authReqBodyType: typeof authReq.body,\n },\n timestamp: Date.now(),\n sessionId: 'debug-session',\n hypothesisId: 'A',\n }),\n }).catch(() => {});\n // #endregion\n\n // Build retry request with fresh CSRF token (re-read from cookie after refresh)\n const retryReq = buildRetryRequest(authReq, tokenDelivery, newToken, config.csrf);\n\n // #region agent log\n fetch('http://127.0.0.1:7242/ingest/97f9fe53-6a8b-43e2-ae9b-4b2d0f725816', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n location: 'auth.interceptor.ts:130',\n message: 'After buildRetryRequest',\n data: {\n retryReqBody: retryReq.body,\n retryReqMethod: retryReq.method,\n retryReqUrl: retryReq.url,\n retryReqBodyType: typeof retryReq.body,\n headersKeys: retryReq.headers.keys(),\n },\n timestamp: Date.now(),\n sessionId: 'debug-session',\n hypothesisId: 'B',\n }),\n }).catch(() => {});\n // #endregion\n\n if (config.debug) {\n console.warn('[nauth-interceptor] Retrying:', req.url);\n }\n\n // Retry the request with fresh token/CSRF\n // IMPORTANT: Errors from the retry (e.g., 400 validation) should NOT trigger\n // session expiration redirect. Only the refresh failure should redirect.\n return next(retryReq).pipe(\n catchError((retryErr) => {\n // Retry failed (could be 400, 403, 500, etc.)\n // Just propagate the error - don't redirect to login\n if (config.debug) {\n console.warn('[nauth-interceptor] Retry request failed:', retryErr);\n }\n return throwError(() => retryErr);\n }),\n );\n }),\n catchError((err) => {\n // This only catches REFRESH failures, not retry failures\n if (config.debug) {\n console.error('[nauth-interceptor] Refresh failed:', err);\n }\n isRefreshing = false;\n refreshTokenSubject.next(null);\n\n // Handle session expiration - redirect to configured URL\n // Only redirect if refresh itself failed (not if retry failed)\n if (config.redirects?.sessionExpired) {\n router.navigateByUrl(config.redirects.sessionExpired).catch((navError) => {\n if (config.debug) {\n console.error('[nauth-interceptor] Navigation failed:', navError);\n }\n });\n }\n\n return throwError(() => err);\n }),\n );\n } else {\n // Wait for ongoing refresh\n if (config.debug) {\n console.warn('[nauth-interceptor] Waiting for refresh...');\n }\n return refreshTokenSubject.pipe(\n filter((token): token is string => token !== null),\n take(1),\n switchMap((token) => {\n if (config.debug) {\n console.warn('[nauth-interceptor] Refresh done, retrying:', req.url);\n }\n const retryReq = buildRetryRequest(authReq, tokenDelivery, token, config.csrf);\n\n // Retry the request - errors here should propagate normally\n // without triggering session expiration redirect\n return next(retryReq).pipe(\n catchError((retryErr) => {\n if (config.debug) {\n console.warn('[nauth-interceptor] Retry request failed:', retryErr);\n }\n return throwError(() => retryErr);\n }),\n );\n }),\n );\n }\n }),\n );\n};\n\n/**\n * Build retry request with appropriate auth.\n *\n * CRITICAL FIX: In cookies mode, after refresh the server may send updated cookies.\n * We MUST re-read the CSRF token from the cookie before retrying to ensure we have\n * the current CSRF token that matches what the server expects.\n *\n * In JSON mode: Clones the request and adds the new Bearer token.\n *\n * @param originalReq - The base request (already has withCredentials if cookies mode)\n * @param tokenDelivery - 'cookies' or 'json'\n * @param newToken - The new access token (JSON mode only)\n * @param csrfConfig - CSRF configuration to re-read token from cookie\n * @returns The request ready for retry with fresh auth\n */\nfunction buildRetryRequest(\n originalReq: HttpRequest<unknown>,\n tokenDelivery: string,\n newToken?: string,\n csrfConfig?: { cookieName?: string; headerName?: string },\n): HttpRequest<unknown> {\n if (tokenDelivery === 'json' && newToken && newToken !== 'success') {\n return originalReq.clone({\n setHeaders: { Authorization: `Bearer ${newToken}` },\n });\n }\n\n // Cookies mode: Browser automatically sends updated httpOnly cookies (access/refresh tokens).\n // However, CSRF token must match the cookie value at the moment of retry.\n // We ALWAYS re-read from document.cookie here (using defaults when csrfConfig\n // is not provided) to avoid stale header values after refresh or across tabs.\n if (tokenDelivery === 'cookies' && ['POST', 'PUT', 'PATCH', 'DELETE'].includes(originalReq.method)) {\n const csrfCookieName = csrfConfig?.cookieName ?? 'nauth_csrf_token';\n const csrfHeaderName = csrfConfig?.headerName ?? 'x-csrf-token';\n const freshCsrfToken = getCsrfToken(csrfCookieName);\n\n // #region agent log\n fetch('http://127.0.0.1:7242/ingest/97f9fe53-6a8b-43e2-ae9b-4b2d0f725816', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n location: 'auth.interceptor.ts:buildRetryRequest',\n message: 'Inside buildRetryRequest cookies branch',\n data: {\n originalReqBody: originalReq.body,\n originalReqBodyType: typeof originalReq.body,\n freshCsrfToken: freshCsrfToken?.substring(0, 8),\n method: originalReq.method,\n },\n timestamp: Date.now(),\n sessionId: 'debug-session',\n hypothesisId: 'C',\n }),\n }).catch(() => {});\n // #endregion\n\n if (freshCsrfToken) {\n // Clone with fresh CSRF token in header\n const cloned = originalReq.clone({\n setHeaders: { [csrfHeaderName]: freshCsrfToken },\n });\n\n // #region agent log\n fetch('http://127.0.0.1:7242/ingest/97f9fe53-6a8b-43e2-ae9b-4b2d0f725816', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n location: 'auth.interceptor.ts:buildRetryRequest:afterClone',\n message: 'After clone with setHeaders',\n data: { clonedBody: cloned.body, clonedBodyType: typeof cloned.body, originalBody: originalReq.body },\n timestamp: Date.now(),\n sessionId: 'debug-session',\n hypothesisId: 'D',\n }),\n }).catch(() => {});\n // #endregion\n\n return cloned;\n }\n }\n\n // No changes needed (GET request or no CSRF token available)\n return originalReq;\n}\n\n/**\n * Class-based interceptor for NgModule compatibility.\n */\nexport class AuthInterceptor {\n intercept(req: HttpRequest<unknown>, next: HttpHandlerFn) {\n return authInterceptor(req, next);\n }\n}\n","import { inject, PLATFORM_ID } from '@angular/core';\nimport { isPlatformBrowser } from '@angular/common';\nimport { type CanActivateFn } from '@angular/router';\nimport { AuthService } from '../ngmodule/auth.service';\nimport { NAUTH_CLIENT_CONFIG } from '../ngmodule/tokens';\nimport { NAuthClientError, NAuthErrorCode } from '@nauth-toolkit/client';\n\n/**\n * Social redirect callback route guard.\n *\n * This guard supports the redirect-first social flow where the backend redirects\n * back to the frontend with:\n * - `appState` (always optional)\n * - `exchangeToken` (present for json/hybrid flows, and for cookie flows that return a challenge)\n * - `error` / `error_description` (provider errors)\n *\n * Behavior:\n * - If `exchangeToken` exists: exchanges it via backend (SDK handles navigation automatically).\n * - If no `exchangeToken`: treat as cookie-success path (SDK handles navigation automatically).\n * - If `error` exists: redirects to oauthError route.\n *\n * @example\n * ```typescript\n * import { socialRedirectCallbackGuard } from '@nauth-toolkit/client/angular';\n *\n * export const routes: Routes = [\n * { path: 'auth/callback', canActivate: [socialRedirectCallbackGuard], component: CallbackComponent },\n * ];\n * ```\n */\nexport const socialRedirectCallbackGuard: CanActivateFn = async (): Promise<boolean> => {\n const auth = inject(AuthService);\n const platformId = inject(PLATFORM_ID);\n const isBrowser = isPlatformBrowser(platformId);\n\n if (!isBrowser) {\n return false;\n }\n\n const params = new URLSearchParams(window.location.search);\n const error = params.get('error');\n const exchangeToken = params.get('exchangeToken');\n const router = auth.getChallengeRouter();\n\n // Provider error: redirect to oauthError\n if (error) {\n await router.navigateToError('oauth');\n return false;\n }\n\n // No exchangeToken: cookie success path; hydrate then navigate to success.\n //\n // Note: we do not \"activate\" the callback route to avoid consumers needing to render a page.\n if (!exchangeToken) {\n // ============================================================================\n // Cookies mode: hydrate user state before redirecting\n // ============================================================================\n // WHY: In cookie delivery, the OAuth callback completes via browser redirects, so the frontend\n // does not receive a JSON AuthResponse to populate the SDK's cached `currentUser`.\n //\n // Without this, sync guards (`authGuard`) can immediately redirect to /login because\n // `currentUser` is still null even though cookies were set successfully.\n try {\n await auth.getProfile();\n await router.navigateToSuccess();\n } catch (err) {\n // Only treat auth failures (401/403) as OAuth errors\n // Network errors or other issues might be temporary - still try success route\n const isAuthError =\n err instanceof NAuthClientError &&\n (err.statusCode === 401 ||\n err.statusCode === 403 ||\n err.code === NAuthErrorCode.AUTH_TOKEN_INVALID ||\n err.code === NAuthErrorCode.AUTH_SESSION_EXPIRED ||\n err.code === NAuthErrorCode.AUTH_SESSION_NOT_FOUND);\n\n if (isAuthError) {\n // Cookies weren't set properly - OAuth failed\n await router.navigateToError('oauth');\n } else {\n // For network errors or other issues, proceed to success route\n // The auth guard will handle authentication state on the next route\n await router.navigateToSuccess();\n }\n }\n return false;\n }\n\n // Exchange token - SDK handles navigation automatically\n await auth.exchangeSocialRedirect(exchangeToken);\n return false;\n};\n","/**\n * Public API Surface of @nauth-toolkit/client-angular (NgModule)\n *\n * This is the default entry point for NgModule-based Angular apps.\n * For standalone components, use: @nauth-toolkit/client-angular/standalone\n */\n\n// Re-export core client types and utilities\nexport * from '@nauth-toolkit/client';\n\n// Export NgModule-specific components (class-based)\nexport * from './ngmodule/tokens';\nexport * from './ngmodule/auth.service';\nexport * from './ngmodule/http-adapter';\nexport * from './ngmodule/auth.interceptor.class';\nexport * from './ngmodule/nauth.module';\n\n// Export functional components (for flexibility in NgModule apps too)\nexport * from './lib/auth.interceptor';\nexport * from './lib/auth.guard';\nexport * from './lib/social-redirect-callback.guard';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.AngularHttpAdapter","isRefreshing","refreshTokenSubject","retriedRequests","getCsrfToken","filter","i2.AuthService"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nauth-toolkit/client-angular",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.62",
|
|
4
4
|
"description": "Angular adapter for nauth-toolkit client SDK",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nauth",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"peerDependencies": {
|
|
25
25
|
"@angular/common": ">=17.0.0",
|
|
26
26
|
"@angular/core": ">=17.0.0",
|
|
27
|
-
"@nauth-toolkit/client": "^0.1.
|
|
27
|
+
"@nauth-toolkit/client": "^0.1.62",
|
|
28
28
|
"rxjs": "^7.0.0 || ^8.0.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|