@nauth-toolkit/client-angular 0.1.56 → 0.1.57

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.
Files changed (66) hide show
  1. package/esm2022/lib/auth.guard.mjs +83 -0
  2. package/esm2022/lib/auth.interceptor.mjs +158 -0
  3. package/esm2022/lib/social-redirect-callback.guard.mjs +81 -0
  4. package/esm2022/nauth-toolkit-client-angular.mjs +5 -0
  5. package/esm2022/ngmodule/auth.interceptor.class.mjs +109 -0
  6. package/esm2022/ngmodule/auth.service.mjs +777 -0
  7. package/esm2022/ngmodule/http-adapter.mjs +81 -0
  8. package/esm2022/ngmodule/nauth.module.mjs +65 -0
  9. package/esm2022/ngmodule/tokens.mjs +6 -0
  10. package/esm2022/public-api.mjs +19 -0
  11. package/esm2022/src/standalone/nauth-toolkit-client-angular-src-standalone.mjs +5 -0
  12. package/esm2022/src/standalone/public-api.mjs +12 -0
  13. package/esm2022/standalone/auth.guard.mjs +83 -0
  14. package/esm2022/standalone/auth.interceptor.mjs +158 -0
  15. package/esm2022/standalone/auth.service.mjs +777 -0
  16. package/esm2022/standalone/http-adapter.mjs +81 -0
  17. package/esm2022/standalone/nauth-toolkit-client-angular-standalone.mjs +5 -0
  18. package/esm2022/standalone/public-api.mjs +16 -0
  19. package/esm2022/standalone/social-redirect-callback.guard.mjs +81 -0
  20. package/esm2022/standalone/tokens.mjs +6 -0
  21. package/fesm2022/nauth-toolkit-client-angular-src-standalone.mjs +17 -0
  22. package/fesm2022/nauth-toolkit-client-angular-src-standalone.mjs.map +1 -0
  23. package/fesm2022/nauth-toolkit-client-angular-standalone.mjs +1183 -0
  24. package/fesm2022/nauth-toolkit-client-angular-standalone.mjs.map +1 -0
  25. package/fesm2022/nauth-toolkit-client-angular.mjs +1344 -0
  26. package/fesm2022/nauth-toolkit-client-angular.mjs.map +1 -0
  27. package/index.d.ts +5 -0
  28. package/{src/lib/auth.guard.ts → lib/auth.guard.d.ts} +15 -37
  29. package/lib/auth.interceptor.d.ts +15 -0
  30. package/lib/social-redirect-callback.guard.d.ts +25 -0
  31. package/ngmodule/auth.interceptor.class.d.ts +34 -0
  32. package/ngmodule/auth.service.d.ts +580 -0
  33. package/ngmodule/http-adapter.d.ts +37 -0
  34. package/ngmodule/nauth.module.d.ts +31 -0
  35. package/{src/ngmodule/tokens.ts → ngmodule/tokens.d.ts} +1 -2
  36. package/package.json +30 -20
  37. package/{src/public-api.ts → public-api.d.ts} +0 -6
  38. package/src/standalone/index.d.ts +5 -0
  39. package/src/standalone/{public-api.ts → public-api.d.ts} +0 -2
  40. package/standalone/{auth.guard.ts → auth.guard.d.ts} +15 -37
  41. package/standalone/auth.interceptor.d.ts +15 -0
  42. package/standalone/auth.service.d.ts +580 -0
  43. package/standalone/http-adapter.d.ts +37 -0
  44. package/standalone/index.d.ts +5 -0
  45. package/standalone/{public-api.ts → public-api.d.ts} +1 -6
  46. package/standalone/social-redirect-callback.guard.d.ts +25 -0
  47. package/standalone/{tokens.ts → tokens.d.ts} +1 -2
  48. package/ng-package.json +0 -12
  49. package/src/lib/auth.interceptor.ts +0 -194
  50. package/src/lib/social-redirect-callback.guard.ts +0 -87
  51. package/src/ngmodule/auth.interceptor.class.ts +0 -124
  52. package/src/ngmodule/auth.service.ts +0 -865
  53. package/src/ngmodule/http-adapter.ts +0 -79
  54. package/src/ngmodule/nauth.module.ts +0 -59
  55. package/src/package.json +0 -11
  56. package/src/standalone/ng-package.json +0 -7
  57. package/src/standalone/package.json +0 -8
  58. package/standalone/auth.interceptor.ts +0 -194
  59. package/standalone/auth.service.ts +0 -865
  60. package/standalone/http-adapter.ts +0 -79
  61. package/standalone/ng-package.json +0 -7
  62. package/standalone/package.json +0 -8
  63. package/standalone/social-redirect-callback.guard.ts +0 -87
  64. package/tsconfig.json +0 -10
  65. package/tsconfig.lib.json +0 -28
  66. package/tsconfig.lib.prod.json +0 -10
@@ -0,0 +1,81 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { HttpErrorResponse } from '@angular/common/http';
3
+ import { firstValueFrom } from 'rxjs';
4
+ import { NAuthClientError, NAuthErrorCode } from '@nauth-toolkit/client';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "@angular/common/http";
7
+ /**
8
+ * HTTP adapter for Angular using HttpClient.
9
+ *
10
+ * This adapter:
11
+ * - Uses Angular's HttpClient for all requests
12
+ * - Works with Angular's HTTP interceptors (including authInterceptor)
13
+ * - Auto-provided via Angular DI (providedIn: 'root')
14
+ * - Converts HttpClient responses to HttpResponse format
15
+ * - Converts HttpErrorResponse to NAuthClientError
16
+ *
17
+ * Users don't need to configure this manually - it's automatically
18
+ * injected when using AuthService in Angular apps.
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * // Automatic usage (no manual setup needed)
23
+ * // AuthService automatically injects AngularHttpAdapter
24
+ * constructor(private auth: AuthService) {}
25
+ * ```
26
+ */
27
+ export class AngularHttpAdapter {
28
+ http;
29
+ constructor(http) {
30
+ this.http = http;
31
+ }
32
+ /**
33
+ * Execute HTTP request using Angular's HttpClient.
34
+ *
35
+ * @param config - Request configuration
36
+ * @returns Response with parsed data
37
+ * @throws NAuthClientError if request fails
38
+ */
39
+ async request(config) {
40
+ try {
41
+ // Use Angular's HttpClient - goes through ALL interceptors
42
+ const data = await firstValueFrom(this.http.request(config.method, config.url, {
43
+ body: config.body,
44
+ headers: config.headers,
45
+ withCredentials: config.credentials === 'include',
46
+ observe: 'body', // Only return body data
47
+ }));
48
+ return {
49
+ data,
50
+ status: 200, // HttpClient only returns data on success
51
+ headers: {}, // Can extract from observe: 'response' if needed
52
+ };
53
+ }
54
+ catch (error) {
55
+ if (error instanceof HttpErrorResponse) {
56
+ // Convert Angular's HttpErrorResponse to NAuthClientError
57
+ const errorData = error.error || {};
58
+ const code = typeof errorData['code'] === 'string' ? errorData.code : NAuthErrorCode.INTERNAL_ERROR;
59
+ const message = typeof errorData['message'] === 'string'
60
+ ? errorData.message
61
+ : error.message || `Request failed with status ${error.status}`;
62
+ const timestamp = typeof errorData['timestamp'] === 'string' ? errorData.timestamp : undefined;
63
+ const details = errorData['details'];
64
+ throw new NAuthClientError(code, message, {
65
+ statusCode: error.status,
66
+ timestamp,
67
+ details,
68
+ isNetworkError: error.status === 0, // Network error (no response from server)
69
+ });
70
+ }
71
+ // Re-throw non-HTTP errors
72
+ throw error;
73
+ }
74
+ }
75
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AngularHttpAdapter, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
76
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AngularHttpAdapter });
77
+ }
78
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AngularHttpAdapter, decorators: [{
79
+ type: Injectable
80
+ }], ctorParameters: () => [{ type: i1.HttpClient }] });
81
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC1hZGFwdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL25nbW9kdWxlL2h0dHAtYWRhcHRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBYyxpQkFBaUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEMsT0FBTyxFQUEwQyxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQzs7O0FBRWpIOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBRUgsTUFBTSxPQUFPLGtCQUFrQjtJQUNBO0lBQTdCLFlBQTZCLElBQWdCO1FBQWhCLFNBQUksR0FBSixJQUFJLENBQVk7SUFBRyxDQUFDO0lBRWpEOzs7Ozs7T0FNRztJQUNILEtBQUssQ0FBQyxPQUFPLENBQUksTUFBbUI7UUFDbEMsSUFBSSxDQUFDO1lBQ0gsMkRBQTJEO1lBQzNELE1BQU0sSUFBSSxHQUFHLE1BQU0sY0FBYyxDQUMvQixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBSSxNQUFNLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxHQUFHLEVBQUU7Z0JBQzlDLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSTtnQkFDakIsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPO2dCQUN2QixlQUFlLEVBQUUsTUFBTSxDQUFDLFdBQVcsS0FBSyxTQUFTO2dCQUNqRCxPQUFPLEVBQUUsTUFBTSxFQUFFLHdCQUF3QjthQUMxQyxDQUFDLENBQ0gsQ0FBQztZQUVGLE9BQU87Z0JBQ0wsSUFBSTtnQkFDSixNQUFNLEVBQUUsR0FBRyxFQUFFLDBDQUEwQztnQkFDdkQsT0FBTyxFQUFFLEVBQUUsRUFBRSxpREFBaUQ7YUFDL0QsQ0FBQztRQUNKLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsSUFBSSxLQUFLLFlBQVksaUJBQWlCLEVBQUUsQ0FBQztnQkFDdkMsMERBQTBEO2dCQUMxRCxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQztnQkFDcEMsTUFBTSxJQUFJLEdBQ1IsT0FBTyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBRSxTQUFTLENBQUMsSUFBdUIsQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FBQztnQkFDN0csTUFBTSxPQUFPLEdBQ1gsT0FBTyxTQUFTLENBQUMsU0FBUyxDQUFDLEtBQUssUUFBUTtvQkFDdEMsQ0FBQyxDQUFFLFNBQVMsQ0FBQyxPQUFrQjtvQkFDL0IsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLElBQUksOEJBQThCLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDcEUsTUFBTSxTQUFTLEdBQUcsT0FBTyxTQUFTLENBQUMsV0FBVyxDQUFDLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7Z0JBQy9GLE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQXdDLENBQUM7Z0JBRTVFLE1BQU0sSUFBSSxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFO29CQUN4QyxVQUFVLEVBQUUsS0FBSyxDQUFDLE1BQU07b0JBQ3hCLFNBQVM7b0JBQ1QsT0FBTztvQkFDUCxjQUFjLEVBQUUsS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsMENBQTBDO2lCQUMvRSxDQUFDLENBQUM7WUFDTCxDQUFDO1lBRUQsMkJBQTJCO1lBQzNCLE1BQU0sS0FBSyxDQUFDO1FBQ2QsQ0FBQztJQUNILENBQUM7d0dBbkRVLGtCQUFrQjs0R0FBbEIsa0JBQWtCOzs0RkFBbEIsa0JBQWtCO2tCQUQ5QixVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSHR0cENsaWVudCwgSHR0cEVycm9yUmVzcG9uc2UgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBmaXJzdFZhbHVlRnJvbSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgSHR0cEFkYXB0ZXIsIEh0dHBSZXF1ZXN0LCBIdHRwUmVzcG9uc2UsIE5BdXRoQ2xpZW50RXJyb3IsIE5BdXRoRXJyb3JDb2RlIH0gZnJvbSAnQG5hdXRoLXRvb2xraXQvY2xpZW50JztcblxuLyoqXG4gKiBIVFRQIGFkYXB0ZXIgZm9yIEFuZ3VsYXIgdXNpbmcgSHR0cENsaWVudC5cbiAqXG4gKiBUaGlzIGFkYXB0ZXI6XG4gKiAtIFVzZXMgQW5ndWxhcidzIEh0dHBDbGllbnQgZm9yIGFsbCByZXF1ZXN0c1xuICogLSBXb3JrcyB3aXRoIEFuZ3VsYXIncyBIVFRQIGludGVyY2VwdG9ycyAoaW5jbHVkaW5nIGF1dGhJbnRlcmNlcHRvcilcbiAqIC0gQXV0by1wcm92aWRlZCB2aWEgQW5ndWxhciBESSAocHJvdmlkZWRJbjogJ3Jvb3QnKVxuICogLSBDb252ZXJ0cyBIdHRwQ2xpZW50IHJlc3BvbnNlcyB0byBIdHRwUmVzcG9uc2UgZm9ybWF0XG4gKiAtIENvbnZlcnRzIEh0dHBFcnJvclJlc3BvbnNlIHRvIE5BdXRoQ2xpZW50RXJyb3JcbiAqXG4gKiBVc2VycyBkb24ndCBuZWVkIHRvIGNvbmZpZ3VyZSB0aGlzIG1hbnVhbGx5IC0gaXQncyBhdXRvbWF0aWNhbGx5XG4gKiBpbmplY3RlZCB3aGVuIHVzaW5nIEF1dGhTZXJ2aWNlIGluIEFuZ3VsYXIgYXBwcy5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gQXV0b21hdGljIHVzYWdlIChubyBtYW51YWwgc2V0dXAgbmVlZGVkKVxuICogLy8gQXV0aFNlcnZpY2UgYXV0b21hdGljYWxseSBpbmplY3RzIEFuZ3VsYXJIdHRwQWRhcHRlclxuICogY29uc3RydWN0b3IocHJpdmF0ZSBhdXRoOiBBdXRoU2VydmljZSkge31cbiAqIGBgYFxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQW5ndWxhckh0dHBBZGFwdGVyIGltcGxlbWVudHMgSHR0cEFkYXB0ZXIge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGh0dHA6IEh0dHBDbGllbnQpIHt9XG5cbiAgLyoqXG4gICAqIEV4ZWN1dGUgSFRUUCByZXF1ZXN0IHVzaW5nIEFuZ3VsYXIncyBIdHRwQ2xpZW50LlxuICAgKlxuICAgKiBAcGFyYW0gY29uZmlnIC0gUmVxdWVzdCBjb25maWd1cmF0aW9uXG4gICAqIEByZXR1cm5zIFJlc3BvbnNlIHdpdGggcGFyc2VkIGRhdGFcbiAgICogQHRocm93cyBOQXV0aENsaWVudEVycm9yIGlmIHJlcXVlc3QgZmFpbHNcbiAgICovXG4gIGFzeW5jIHJlcXVlc3Q8VD4oY29uZmlnOiBIdHRwUmVxdWVzdCk6IFByb21pc2U8SHR0cFJlc3BvbnNlPFQ+PiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIFVzZSBBbmd1bGFyJ3MgSHR0cENsaWVudCAtIGdvZXMgdGhyb3VnaCBBTEwgaW50ZXJjZXB0b3JzXG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgZmlyc3RWYWx1ZUZyb20oXG4gICAgICAgIHRoaXMuaHR0cC5yZXF1ZXN0PFQ+KGNvbmZpZy5tZXRob2QsIGNvbmZpZy51cmwsIHtcbiAgICAgICAgICBib2R5OiBjb25maWcuYm9keSxcbiAgICAgICAgICBoZWFkZXJzOiBjb25maWcuaGVhZGVycyxcbiAgICAgICAgICB3aXRoQ3JlZGVudGlhbHM6IGNvbmZpZy5jcmVkZW50aWFscyA9PT0gJ2luY2x1ZGUnLFxuICAgICAgICAgIG9ic2VydmU6ICdib2R5JywgLy8gT25seSByZXR1cm4gYm9keSBkYXRhXG4gICAgICAgIH0pLFxuICAgICAgKTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZGF0YSxcbiAgICAgICAgc3RhdHVzOiAyMDAsIC8vIEh0dHBDbGllbnQgb25seSByZXR1cm5zIGRhdGEgb24gc3VjY2Vzc1xuICAgICAgICBoZWFkZXJzOiB7fSwgLy8gQ2FuIGV4dHJhY3QgZnJvbSBvYnNlcnZlOiAncmVzcG9uc2UnIGlmIG5lZWRlZFxuICAgICAgfTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgSHR0cEVycm9yUmVzcG9uc2UpIHtcbiAgICAgICAgLy8gQ29udmVydCBBbmd1bGFyJ3MgSHR0cEVycm9yUmVzcG9uc2UgdG8gTkF1dGhDbGllbnRFcnJvclxuICAgICAgICBjb25zdCBlcnJvckRhdGEgPSBlcnJvci5lcnJvciB8fCB7fTtcbiAgICAgICAgY29uc3QgY29kZSA9XG4gICAgICAgICAgdHlwZW9mIGVycm9yRGF0YVsnY29kZSddID09PSAnc3RyaW5nJyA/IChlcnJvckRhdGEuY29kZSBhcyBOQXV0aEVycm9yQ29kZSkgOiBOQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUjtcbiAgICAgICAgY29uc3QgbWVzc2FnZSA9XG4gICAgICAgICAgdHlwZW9mIGVycm9yRGF0YVsnbWVzc2FnZSddID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgPyAoZXJyb3JEYXRhLm1lc3NhZ2UgYXMgc3RyaW5nKVxuICAgICAgICAgICAgOiBlcnJvci5tZXNzYWdlIHx8IGBSZXF1ZXN0IGZhaWxlZCB3aXRoIHN0YXR1cyAke2Vycm9yLnN0YXR1c31gO1xuICAgICAgICBjb25zdCB0aW1lc3RhbXAgPSB0eXBlb2YgZXJyb3JEYXRhWyd0aW1lc3RhbXAnXSA9PT0gJ3N0cmluZycgPyBlcnJvckRhdGEudGltZXN0YW1wIDogdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBkZXRhaWxzID0gZXJyb3JEYXRhWydkZXRhaWxzJ10gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCB1bmRlZmluZWQ7XG5cbiAgICAgICAgdGhyb3cgbmV3IE5BdXRoQ2xpZW50RXJyb3IoY29kZSwgbWVzc2FnZSwge1xuICAgICAgICAgIHN0YXR1c0NvZGU6IGVycm9yLnN0YXR1cyxcbiAgICAgICAgICB0aW1lc3RhbXAsXG4gICAgICAgICAgZGV0YWlscyxcbiAgICAgICAgICBpc05ldHdvcmtFcnJvcjogZXJyb3Iuc3RhdHVzID09PSAwLCAvLyBOZXR3b3JrIGVycm9yIChubyByZXNwb25zZSBmcm9tIHNlcnZlcilcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIFJlLXRocm93IG5vbi1IVFRQIGVycm9yc1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG59XG4iXX0=
@@ -0,0 +1,65 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
3
+ import { NAUTH_CLIENT_CONFIG } from './tokens';
4
+ import { AuthService } from './auth.service';
5
+ import { AngularHttpAdapter } from './http-adapter';
6
+ import { AuthInterceptorClass } from './auth.interceptor.class';
7
+ import * as i0 from "@angular/core";
8
+ /**
9
+ * NgModule for nauth-toolkit Angular integration.
10
+ *
11
+ * Use this for NgModule-based apps (Angular 17+ with NgModule or legacy apps).
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // app.module.ts
16
+ * import { NAuthModule } from '@nauth-toolkit/client-angular';
17
+ *
18
+ * @NgModule({
19
+ * imports: [
20
+ * NAuthModule.forRoot({
21
+ * baseUrl: 'http://localhost:3000/auth',
22
+ * tokenDelivery: 'cookies',
23
+ * }),
24
+ * ],
25
+ * })
26
+ * export class AppModule {}
27
+ * ```
28
+ */
29
+ export class NAuthModule {
30
+ static forRoot(config) {
31
+ return {
32
+ ngModule: NAuthModule,
33
+ providers: [
34
+ {
35
+ provide: NAUTH_CLIENT_CONFIG,
36
+ useValue: config,
37
+ },
38
+ AngularHttpAdapter,
39
+ {
40
+ provide: AuthService,
41
+ useFactory: (httpAdapter) => {
42
+ return new AuthService(config, httpAdapter);
43
+ },
44
+ deps: [AngularHttpAdapter],
45
+ },
46
+ {
47
+ provide: HTTP_INTERCEPTORS,
48
+ useClass: AuthInterceptorClass,
49
+ multi: true,
50
+ },
51
+ ],
52
+ };
53
+ }
54
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NAuthModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
55
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.12", ngImport: i0, type: NAuthModule, imports: [HttpClientModule], exports: [HttpClientModule] });
56
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NAuthModule, imports: [HttpClientModule, HttpClientModule] });
57
+ }
58
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NAuthModule, decorators: [{
59
+ type: NgModule,
60
+ args: [{
61
+ imports: [HttpClientModule],
62
+ exports: [HttpClientModule],
63
+ }]
64
+ }] });
65
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF1dGgubW9kdWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL25nbW9kdWxlL25hdXRoLm1vZHVsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUF1QixNQUFNLGVBQWUsQ0FBQztBQUM5RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUMzRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDL0MsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDBCQUEwQixDQUFDOztBQUdoRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFLSCxNQUFNLE9BQU8sV0FBVztJQUN0QixNQUFNLENBQUMsT0FBTyxDQUFDLE1BQXlCO1FBQ3RDLE9BQU87WUFDTCxRQUFRLEVBQUUsV0FBVztZQUNyQixTQUFTLEVBQUU7Z0JBQ1Q7b0JBQ0UsT0FBTyxFQUFFLG1CQUFtQjtvQkFDNUIsUUFBUSxFQUFFLE1BQU07aUJBQ2pCO2dCQUNELGtCQUFrQjtnQkFDbEI7b0JBQ0UsT0FBTyxFQUFFLFdBQVc7b0JBQ3BCLFVBQVUsRUFBRSxDQUFDLFdBQStCLEVBQUUsRUFBRTt3QkFDOUMsT0FBTyxJQUFJLFdBQVcsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUM7b0JBQzlDLENBQUM7b0JBQ0QsSUFBSSxFQUFFLENBQUMsa0JBQWtCLENBQUM7aUJBQzNCO2dCQUNEO29CQUNFLE9BQU8sRUFBRSxpQkFBaUI7b0JBQzFCLFFBQVEsRUFBRSxvQkFBb0I7b0JBQzlCLEtBQUssRUFBRSxJQUFJO2lCQUNaO2FBQ0Y7U0FDRixDQUFDO0lBQ0osQ0FBQzt3R0F4QlUsV0FBVzt5R0FBWCxXQUFXLFlBSFosZ0JBQWdCLGFBQ2hCLGdCQUFnQjt5R0FFZixXQUFXLFlBSFosZ0JBQWdCLEVBQ2hCLGdCQUFnQjs7NEZBRWYsV0FBVztrQkFKdkIsUUFBUTttQkFBQztvQkFDUixPQUFPLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQztvQkFDM0IsT0FBTyxFQUFFLENBQUMsZ0JBQWdCLENBQUM7aUJBQzVCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTmdNb2R1bGUsIE1vZHVsZVdpdGhQcm92aWRlcnMgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEh0dHBDbGllbnRNb2R1bGUsIEhUVFBfSU5URVJDRVBUT1JTIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgTkFVVEhfQ0xJRU5UX0NPTkZJRyB9IGZyb20gJy4vdG9rZW5zJztcbmltcG9ydCB7IEF1dGhTZXJ2aWNlIH0gZnJvbSAnLi9hdXRoLnNlcnZpY2UnO1xuaW1wb3J0IHsgQW5ndWxhckh0dHBBZGFwdGVyIH0gZnJvbSAnLi9odHRwLWFkYXB0ZXInO1xuaW1wb3J0IHsgQXV0aEludGVyY2VwdG9yQ2xhc3MgfSBmcm9tICcuL2F1dGguaW50ZXJjZXB0b3IuY2xhc3MnO1xuaW1wb3J0IHsgTkF1dGhDbGllbnRDb25maWcgfSBmcm9tICdAbmF1dGgtdG9vbGtpdC9jbGllbnQnO1xuXG4vKipcbiAqIE5nTW9kdWxlIGZvciBuYXV0aC10b29sa2l0IEFuZ3VsYXIgaW50ZWdyYXRpb24uXG4gKlxuICogVXNlIHRoaXMgZm9yIE5nTW9kdWxlLWJhc2VkIGFwcHMgKEFuZ3VsYXIgMTcrIHdpdGggTmdNb2R1bGUgb3IgbGVnYWN5IGFwcHMpLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBhcHAubW9kdWxlLnRzXG4gKiBpbXBvcnQgeyBOQXV0aE1vZHVsZSB9IGZyb20gJ0BuYXV0aC10b29sa2l0L2NsaWVudC1hbmd1bGFyJztcbiAqXG4gKiBATmdNb2R1bGUoe1xuICogICBpbXBvcnRzOiBbXG4gKiAgICAgTkF1dGhNb2R1bGUuZm9yUm9vdCh7XG4gKiAgICAgICBiYXNlVXJsOiAnaHR0cDovL2xvY2FsaG9zdDozMDAwL2F1dGgnLFxuICogICAgICAgdG9rZW5EZWxpdmVyeTogJ2Nvb2tpZXMnLFxuICogICAgIH0pLFxuICogICBdLFxuICogfSlcbiAqIGV4cG9ydCBjbGFzcyBBcHBNb2R1bGUge31cbiAqIGBgYFxuICovXG5ATmdNb2R1bGUoe1xuICBpbXBvcnRzOiBbSHR0cENsaWVudE1vZHVsZV0sXG4gIGV4cG9ydHM6IFtIdHRwQ2xpZW50TW9kdWxlXSxcbn0pXG5leHBvcnQgY2xhc3MgTkF1dGhNb2R1bGUge1xuICBzdGF0aWMgZm9yUm9vdChjb25maWc6IE5BdXRoQ2xpZW50Q29uZmlnKTogTW9kdWxlV2l0aFByb3ZpZGVyczxOQXV0aE1vZHVsZT4ge1xuICAgIHJldHVybiB7XG4gICAgICBuZ01vZHVsZTogTkF1dGhNb2R1bGUsXG4gICAgICBwcm92aWRlcnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIHByb3ZpZGU6IE5BVVRIX0NMSUVOVF9DT05GSUcsXG4gICAgICAgICAgdXNlVmFsdWU6IGNvbmZpZyxcbiAgICAgICAgfSxcbiAgICAgICAgQW5ndWxhckh0dHBBZGFwdGVyLFxuICAgICAgICB7XG4gICAgICAgICAgcHJvdmlkZTogQXV0aFNlcnZpY2UsXG4gICAgICAgICAgdXNlRmFjdG9yeTogKGh0dHBBZGFwdGVyOiBBbmd1bGFySHR0cEFkYXB0ZXIpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgQXV0aFNlcnZpY2UoY29uZmlnLCBodHRwQWRhcHRlcik7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBkZXBzOiBbQW5ndWxhckh0dHBBZGFwdGVyXSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHByb3ZpZGU6IEhUVFBfSU5URVJDRVBUT1JTLFxuICAgICAgICAgIHVzZUNsYXNzOiBBdXRoSW50ZXJjZXB0b3JDbGFzcyxcbiAgICAgICAgICBtdWx0aTogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxufVxuIl19
@@ -0,0 +1,6 @@
1
+ import { InjectionToken } from '@angular/core';
2
+ /**
3
+ * Injection token for providing NAuthClientConfig in Angular apps.
4
+ */
5
+ export const NAUTH_CLIENT_CONFIG = new InjectionToken('NAUTH_CLIENT_CONFIG');
6
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL25nbW9kdWxlL3Rva2Vucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRy9DOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxjQUFjLENBQW9CLHFCQUFxQixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3Rpb25Ub2tlbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTkF1dGhDbGllbnRDb25maWcgfSBmcm9tICdAbmF1dGgtdG9vbGtpdC9jbGllbnQnO1xuXG4vKipcbiAqIEluamVjdGlvbiB0b2tlbiBmb3IgcHJvdmlkaW5nIE5BdXRoQ2xpZW50Q29uZmlnIGluIEFuZ3VsYXIgYXBwcy5cbiAqL1xuZXhwb3J0IGNvbnN0IE5BVVRIX0NMSUVOVF9DT05GSUcgPSBuZXcgSW5qZWN0aW9uVG9rZW48TkF1dGhDbGllbnRDb25maWc+KCdOQVVUSF9DTElFTlRfQ09ORklHJyk7XG4iXX0=
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Public API Surface of @nauth-toolkit/client-angular (NgModule)
3
+ *
4
+ * This is the default entry point for NgModule-based Angular apps.
5
+ * For standalone components, use: @nauth-toolkit/client-angular/standalone
6
+ */
7
+ // Re-export core client types and utilities
8
+ export * from '@nauth-toolkit/client';
9
+ // Export NgModule-specific components (class-based)
10
+ export * from './ngmodule/tokens';
11
+ export * from './ngmodule/auth.service';
12
+ export * from './ngmodule/http-adapter';
13
+ export * from './ngmodule/auth.interceptor.class';
14
+ export * from './ngmodule/nauth.module';
15
+ // Export functional components (for flexibility in NgModule apps too)
16
+ export * from './lib/auth.interceptor';
17
+ export * from './lib/auth.guard';
18
+ export * from './lib/social-redirect-callback.guard';
19
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wdWJsaWMtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7OztHQUtHO0FBRUgsNENBQTRDO0FBQzVDLGNBQWMsdUJBQXVCLENBQUM7QUFFdEMsb0RBQW9EO0FBQ3BELGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLHlCQUF5QixDQUFDO0FBQ3hDLGNBQWMsbUNBQW1DLENBQUM7QUFDbEQsY0FBYyx5QkFBeUIsQ0FBQztBQUV4QyxzRUFBc0U7QUFDdEUsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLGtCQUFrQixDQUFDO0FBQ2pDLGNBQWMsc0NBQXNDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFB1YmxpYyBBUEkgU3VyZmFjZSBvZiBAbmF1dGgtdG9vbGtpdC9jbGllbnQtYW5ndWxhciAoTmdNb2R1bGUpXG4gKlxuICogVGhpcyBpcyB0aGUgZGVmYXVsdCBlbnRyeSBwb2ludCBmb3IgTmdNb2R1bGUtYmFzZWQgQW5ndWxhciBhcHBzLlxuICogRm9yIHN0YW5kYWxvbmUgY29tcG9uZW50cywgdXNlOiBAbmF1dGgtdG9vbGtpdC9jbGllbnQtYW5ndWxhci9zdGFuZGFsb25lXG4gKi9cblxuLy8gUmUtZXhwb3J0IGNvcmUgY2xpZW50IHR5cGVzIGFuZCB1dGlsaXRpZXNcbmV4cG9ydCAqIGZyb20gJ0BuYXV0aC10b29sa2l0L2NsaWVudCc7XG5cbi8vIEV4cG9ydCBOZ01vZHVsZS1zcGVjaWZpYyBjb21wb25lbnRzIChjbGFzcy1iYXNlZClcbmV4cG9ydCAqIGZyb20gJy4vbmdtb2R1bGUvdG9rZW5zJztcbmV4cG9ydCAqIGZyb20gJy4vbmdtb2R1bGUvYXV0aC5zZXJ2aWNlJztcbmV4cG9ydCAqIGZyb20gJy4vbmdtb2R1bGUvaHR0cC1hZGFwdGVyJztcbmV4cG9ydCAqIGZyb20gJy4vbmdtb2R1bGUvYXV0aC5pbnRlcmNlcHRvci5jbGFzcyc7XG5leHBvcnQgKiBmcm9tICcuL25nbW9kdWxlL25hdXRoLm1vZHVsZSc7XG5cbi8vIEV4cG9ydCBmdW5jdGlvbmFsIGNvbXBvbmVudHMgKGZvciBmbGV4aWJpbGl0eSBpbiBOZ01vZHVsZSBhcHBzIHRvbylcbmV4cG9ydCAqIGZyb20gJy4vbGliL2F1dGguaW50ZXJjZXB0b3InO1xuZXhwb3J0ICogZnJvbSAnLi9saWIvYXV0aC5ndWFyZCc7XG5leHBvcnQgKiBmcm9tICcuL2xpYi9zb2NpYWwtcmVkaXJlY3QtY2FsbGJhY2suZ3VhcmQnO1xuIl19
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ export * from './public-api';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF1dGgtdG9vbGtpdC1jbGllbnQtYW5ndWxhci1zcmMtc3RhbmRhbG9uZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9zdGFuZGFsb25lL25hdXRoLXRvb2xraXQtY2xpZW50LWFuZ3VsYXItc3JjLXN0YW5kYWxvbmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLGNBQWMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9wdWJsaWMtYXBpJztcbiJdfQ==
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Public API Surface of @nauth-toolkit/client-angular/standalone
3
+ *
4
+ * This entry point is for standalone component-based Angular apps (Angular 14+).
5
+ * For NgModule apps, use: @nauth-toolkit/client-angular
6
+ *
7
+ * NOTE: This simply re-exports the main entry point since both share the same code for now.
8
+ * The split allows future additions like `provideNAuth()` for standalone apps.
9
+ */
10
+ // Re-export everything from the main entry point
11
+ export * from '@nauth-toolkit/client-angular';
12
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9zdGFuZGFsb25lL3B1YmxpYy1hcGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7O0dBUUc7QUFFSCxpREFBaUQ7QUFDakQsY0FBYywrQkFBK0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUHVibGljIEFQSSBTdXJmYWNlIG9mIEBuYXV0aC10b29sa2l0L2NsaWVudC1hbmd1bGFyL3N0YW5kYWxvbmVcbiAqXG4gKiBUaGlzIGVudHJ5IHBvaW50IGlzIGZvciBzdGFuZGFsb25lIGNvbXBvbmVudC1iYXNlZCBBbmd1bGFyIGFwcHMgKEFuZ3VsYXIgMTQrKS5cbiAqIEZvciBOZ01vZHVsZSBhcHBzLCB1c2U6IEBuYXV0aC10b29sa2l0L2NsaWVudC1hbmd1bGFyXG4gKlxuICogTk9URTogVGhpcyBzaW1wbHkgcmUtZXhwb3J0cyB0aGUgbWFpbiBlbnRyeSBwb2ludCBzaW5jZSBib3RoIHNoYXJlIHRoZSBzYW1lIGNvZGUgZm9yIG5vdy5cbiAqIFRoZSBzcGxpdCBhbGxvd3MgZnV0dXJlIGFkZGl0aW9ucyBsaWtlIGBwcm92aWRlTkF1dGgoKWAgZm9yIHN0YW5kYWxvbmUgYXBwcy5cbiAqL1xuXG4vLyBSZS1leHBvcnQgZXZlcnl0aGluZyBmcm9tIHRoZSBtYWluIGVudHJ5IHBvaW50XG5leHBvcnQgKiBmcm9tICdAbmF1dGgtdG9vbGtpdC9jbGllbnQtYW5ndWxhcic7XG4iXX0=
@@ -0,0 +1,83 @@
1
+ import { inject } from '@angular/core';
2
+ import { Router } from '@angular/router';
3
+ import { AuthService } from './auth.service';
4
+ /**
5
+ * Functional route guard for authentication (Angular 17+).
6
+ *
7
+ * Protects routes by checking if user is authenticated.
8
+ * Redirects to login page if not authenticated.
9
+ *
10
+ * @param redirectTo - Path to redirect to if not authenticated (default: '/login')
11
+ * @returns CanActivateFn guard function
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // In route configuration
16
+ * const routes: Routes = [
17
+ * {
18
+ * path: 'home',
19
+ * component: HomeComponent,
20
+ * canActivate: [authGuard()]
21
+ * },
22
+ * {
23
+ * path: 'admin',
24
+ * component: AdminComponent,
25
+ * canActivate: [authGuard('/admin/login')]
26
+ * }
27
+ * ];
28
+ * ```
29
+ */
30
+ export function authGuard(redirectTo = '/login') {
31
+ return () => {
32
+ const auth = inject(AuthService);
33
+ const router = inject(Router);
34
+ if (auth.isAuthenticated()) {
35
+ return true;
36
+ }
37
+ return router.createUrlTree([redirectTo]);
38
+ };
39
+ }
40
+ /**
41
+ * Class-based authentication guard for NgModule compatibility.
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * // In route configuration (NgModule)
46
+ * const routes: Routes = [
47
+ * {
48
+ * path: 'home',
49
+ * component: HomeComponent,
50
+ * canActivate: [AuthGuard]
51
+ * }
52
+ * ];
53
+ *
54
+ * // In module providers
55
+ * @NgModule({
56
+ * providers: [AuthGuard]
57
+ * })
58
+ * ```
59
+ */
60
+ export class AuthGuard {
61
+ auth;
62
+ router;
63
+ /**
64
+ * @param auth - Authentication service
65
+ * @param router - Angular router
66
+ */
67
+ constructor(auth, router) {
68
+ this.auth = auth;
69
+ this.router = router;
70
+ }
71
+ /**
72
+ * Check if route can be activated.
73
+ *
74
+ * @returns True if authenticated, otherwise redirects to login
75
+ */
76
+ canActivate() {
77
+ if (this.auth.isAuthenticated()) {
78
+ return true;
79
+ }
80
+ return this.router.createUrlTree(['/login']);
81
+ }
82
+ }
83
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5ndWFyZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3N0YW5kYWxvbmUvYXV0aC5ndWFyZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZDLE9BQU8sRUFBaUIsTUFBTSxFQUFXLE1BQU0saUJBQWlCLENBQUM7QUFDakUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTdDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBeUJHO0FBQ0gsTUFBTSxVQUFVLFNBQVMsQ0FBQyxVQUFVLEdBQUcsUUFBUTtJQUM3QyxPQUFPLEdBQXNCLEVBQUU7UUFDN0IsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ2pDLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUU5QixJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUUsRUFBRSxDQUFDO1lBQzNCLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUVELE9BQU8sTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFDNUMsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBQ0gsTUFBTSxPQUFPLFNBQVM7SUFNVjtJQUNBO0lBTlY7OztPQUdHO0lBQ0gsWUFDVSxJQUFpQixFQUNqQixNQUFjO1FBRGQsU0FBSSxHQUFKLElBQUksQ0FBYTtRQUNqQixXQUFNLEdBQU4sTUFBTSxDQUFRO0lBQ3JCLENBQUM7SUFFSjs7OztPQUlHO0lBQ0gsV0FBVztRQUNULElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsRUFBRSxDQUFDO1lBQ2hDLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBQy9DLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ2FuQWN0aXZhdGVGbiwgUm91dGVyLCBVcmxUcmVlIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IEF1dGhTZXJ2aWNlIH0gZnJvbSAnLi9hdXRoLnNlcnZpY2UnO1xuXG4vKipcbiAqIEZ1bmN0aW9uYWwgcm91dGUgZ3VhcmQgZm9yIGF1dGhlbnRpY2F0aW9uIChBbmd1bGFyIDE3KykuXG4gKlxuICogUHJvdGVjdHMgcm91dGVzIGJ5IGNoZWNraW5nIGlmIHVzZXIgaXMgYXV0aGVudGljYXRlZC5cbiAqIFJlZGlyZWN0cyB0byBsb2dpbiBwYWdlIGlmIG5vdCBhdXRoZW50aWNhdGVkLlxuICpcbiAqIEBwYXJhbSByZWRpcmVjdFRvIC0gUGF0aCB0byByZWRpcmVjdCB0byBpZiBub3QgYXV0aGVudGljYXRlZCAoZGVmYXVsdDogJy9sb2dpbicpXG4gKiBAcmV0dXJucyBDYW5BY3RpdmF0ZUZuIGd1YXJkIGZ1bmN0aW9uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIEluIHJvdXRlIGNvbmZpZ3VyYXRpb25cbiAqIGNvbnN0IHJvdXRlczogUm91dGVzID0gW1xuICogICB7XG4gKiAgICAgcGF0aDogJ2hvbWUnLFxuICogICAgIGNvbXBvbmVudDogSG9tZUNvbXBvbmVudCxcbiAqICAgICBjYW5BY3RpdmF0ZTogW2F1dGhHdWFyZCgpXVxuICogICB9LFxuICogICB7XG4gKiAgICAgcGF0aDogJ2FkbWluJyxcbiAqICAgICBjb21wb25lbnQ6IEFkbWluQ29tcG9uZW50LFxuICogICAgIGNhbkFjdGl2YXRlOiBbYXV0aEd1YXJkKCcvYWRtaW4vbG9naW4nKV1cbiAqICAgfVxuICogXTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gYXV0aEd1YXJkKHJlZGlyZWN0VG8gPSAnL2xvZ2luJyk6IENhbkFjdGl2YXRlRm4ge1xuICByZXR1cm4gKCk6IGJvb2xlYW4gfCBVcmxUcmVlID0+IHtcbiAgICBjb25zdCBhdXRoID0gaW5qZWN0KEF1dGhTZXJ2aWNlKTtcbiAgICBjb25zdCByb3V0ZXIgPSBpbmplY3QoUm91dGVyKTtcblxuICAgIGlmIChhdXRoLmlzQXV0aGVudGljYXRlZCgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gcm91dGVyLmNyZWF0ZVVybFRyZWUoW3JlZGlyZWN0VG9dKTtcbiAgfTtcbn1cblxuLyoqXG4gKiBDbGFzcy1iYXNlZCBhdXRoZW50aWNhdGlvbiBndWFyZCBmb3IgTmdNb2R1bGUgY29tcGF0aWJpbGl0eS5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gSW4gcm91dGUgY29uZmlndXJhdGlvbiAoTmdNb2R1bGUpXG4gKiBjb25zdCByb3V0ZXM6IFJvdXRlcyA9IFtcbiAqICAge1xuICogICAgIHBhdGg6ICdob21lJyxcbiAqICAgICBjb21wb25lbnQ6IEhvbWVDb21wb25lbnQsXG4gKiAgICAgY2FuQWN0aXZhdGU6IFtBdXRoR3VhcmRdXG4gKiAgIH1cbiAqIF07XG4gKlxuICogLy8gSW4gbW9kdWxlIHByb3ZpZGVyc1xuICogQE5nTW9kdWxlKHtcbiAqICAgcHJvdmlkZXJzOiBbQXV0aEd1YXJkXVxuICogfSlcbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgQXV0aEd1YXJkIHtcbiAgLyoqXG4gICAqIEBwYXJhbSBhdXRoIC0gQXV0aGVudGljYXRpb24gc2VydmljZVxuICAgKiBAcGFyYW0gcm91dGVyIC0gQW5ndWxhciByb3V0ZXJcbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgYXV0aDogQXV0aFNlcnZpY2UsXG4gICAgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlcixcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiByb3V0ZSBjYW4gYmUgYWN0aXZhdGVkLlxuICAgKlxuICAgKiBAcmV0dXJucyBUcnVlIGlmIGF1dGhlbnRpY2F0ZWQsIG90aGVyd2lzZSByZWRpcmVjdHMgdG8gbG9naW5cbiAgICovXG4gIGNhbkFjdGl2YXRlKCk6IGJvb2xlYW4gfCBVcmxUcmVlIHtcbiAgICBpZiAodGhpcy5hdXRoLmlzQXV0aGVudGljYXRlZCgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5yb3V0ZXIuY3JlYXRlVXJsVHJlZShbJy9sb2dpbiddKTtcbiAgfVxufVxuIl19
@@ -0,0 +1,158 @@
1
+ import { inject, PLATFORM_ID } from '@angular/core';
2
+ import { isPlatformBrowser } from '@angular/common';
3
+ import { HttpClient, HttpErrorResponse } from '@angular/common/http';
4
+ import { Router } from '@angular/router';
5
+ import { catchError, switchMap, throwError, filter, take, BehaviorSubject, from } from 'rxjs';
6
+ import { NAUTH_CLIENT_CONFIG } from './tokens';
7
+ import { AuthService } from './auth.service';
8
+ /**
9
+ * Refresh state management.
10
+ * BehaviorSubject pattern is the industry-standard for token refresh.
11
+ */
12
+ let isRefreshing = false;
13
+ const refreshTokenSubject = new BehaviorSubject(null);
14
+ /**
15
+ * Track retried requests to prevent infinite loops.
16
+ */
17
+ const retriedRequests = new WeakSet();
18
+ /**
19
+ * Get CSRF token from cookie.
20
+ */
21
+ function getCsrfToken(cookieName) {
22
+ if (typeof document === 'undefined')
23
+ return null;
24
+ const match = document.cookie.match(new RegExp(`(^| )${cookieName}=([^;]+)`));
25
+ return match ? decodeURIComponent(match[2]) : null;
26
+ }
27
+ /**
28
+ * Angular HTTP interceptor for nauth-toolkit.
29
+ *
30
+ * Handles:
31
+ * - Cookies mode: withCredentials + CSRF tokens + refresh via POST
32
+ * - JSON mode: refresh via SDK, retry with new token
33
+ */
34
+ export const authInterceptor = (req, next) => {
35
+ const config = inject(NAUTH_CLIENT_CONFIG);
36
+ const http = inject(HttpClient);
37
+ const authService = inject(AuthService);
38
+ const platformId = inject(PLATFORM_ID);
39
+ const router = inject(Router);
40
+ const isBrowser = isPlatformBrowser(platformId);
41
+ if (!isBrowser) {
42
+ return next(req);
43
+ }
44
+ const tokenDelivery = config.tokenDelivery;
45
+ const baseUrl = config.baseUrl;
46
+ const endpoints = config.endpoints ?? {};
47
+ const refreshPath = endpoints.refresh ?? '/refresh';
48
+ const loginPath = endpoints.login ?? '/login';
49
+ const signupPath = endpoints.signup ?? '/signup';
50
+ const socialExchangePath = endpoints.socialExchange ?? '/social/exchange';
51
+ const refreshUrl = `${baseUrl}${refreshPath}`;
52
+ const isAuthApiRequest = req.url.includes(baseUrl);
53
+ const isRefreshEndpoint = req.url.includes(refreshPath);
54
+ const isPublicEndpoint = req.url.includes(loginPath) || req.url.includes(signupPath) || req.url.includes(socialExchangePath);
55
+ // Build request with credentials (cookies mode only)
56
+ let authReq = req;
57
+ if (tokenDelivery === 'cookies') {
58
+ authReq = authReq.clone({ withCredentials: true });
59
+ if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method)) {
60
+ const csrfCookieName = config.csrf?.cookieName ?? 'nauth_csrf_token';
61
+ const csrfHeaderName = config.csrf?.headerName ?? 'x-csrf-token';
62
+ const csrfToken = getCsrfToken(csrfCookieName);
63
+ if (csrfToken) {
64
+ authReq = authReq.clone({ setHeaders: { [csrfHeaderName]: csrfToken } });
65
+ }
66
+ }
67
+ }
68
+ return next(authReq).pipe(catchError((error) => {
69
+ const shouldHandle = error instanceof HttpErrorResponse &&
70
+ error.status === 401 &&
71
+ isAuthApiRequest &&
72
+ !isRefreshEndpoint &&
73
+ !isPublicEndpoint &&
74
+ !retriedRequests.has(req);
75
+ if (!shouldHandle) {
76
+ return throwError(() => error);
77
+ }
78
+ if (config.debug) {
79
+ console.warn('[nauth-interceptor] 401 detected:', req.url);
80
+ }
81
+ if (!isRefreshing) {
82
+ isRefreshing = true;
83
+ refreshTokenSubject.next(null);
84
+ if (config.debug) {
85
+ console.warn('[nauth-interceptor] Starting refresh...');
86
+ }
87
+ // Refresh based on mode
88
+ const refresh$ = tokenDelivery === 'cookies'
89
+ ? http.post(refreshUrl, {}, { withCredentials: true })
90
+ : from(authService.refresh());
91
+ return refresh$.pipe(switchMap((response) => {
92
+ if (config.debug) {
93
+ console.warn('[nauth-interceptor] Refresh successful');
94
+ }
95
+ isRefreshing = false;
96
+ // Get new token (JSON mode) or signal success (cookies mode)
97
+ const newToken = 'accessToken' in response ? response.accessToken : 'success';
98
+ refreshTokenSubject.next(newToken ?? 'success');
99
+ // Build retry request
100
+ const retryReq = buildRetryRequest(authReq, tokenDelivery, newToken);
101
+ retriedRequests.add(retryReq);
102
+ if (config.debug) {
103
+ console.warn('[nauth-interceptor] Retrying:', req.url);
104
+ }
105
+ return next(retryReq);
106
+ }), catchError((err) => {
107
+ if (config.debug) {
108
+ console.error('[nauth-interceptor] Refresh failed:', err);
109
+ }
110
+ isRefreshing = false;
111
+ refreshTokenSubject.next(null);
112
+ // Handle session expiration - redirect to configured URL
113
+ if (config.redirects?.sessionExpired) {
114
+ router.navigateByUrl(config.redirects.sessionExpired).catch((navError) => {
115
+ if (config.debug) {
116
+ console.error('[nauth-interceptor] Navigation failed:', navError);
117
+ }
118
+ });
119
+ }
120
+ return throwError(() => err);
121
+ }));
122
+ }
123
+ else {
124
+ // Wait for ongoing refresh
125
+ if (config.debug) {
126
+ console.warn('[nauth-interceptor] Waiting for refresh...');
127
+ }
128
+ return refreshTokenSubject.pipe(filter((token) => token !== null), take(1), switchMap((token) => {
129
+ if (config.debug) {
130
+ console.warn('[nauth-interceptor] Refresh done, retrying:', req.url);
131
+ }
132
+ const retryReq = buildRetryRequest(authReq, tokenDelivery, token);
133
+ retriedRequests.add(retryReq);
134
+ return next(retryReq);
135
+ }));
136
+ }
137
+ }));
138
+ };
139
+ /**
140
+ * Build retry request with appropriate auth.
141
+ */
142
+ function buildRetryRequest(originalReq, tokenDelivery, newToken) {
143
+ if (tokenDelivery === 'json' && newToken && newToken !== 'success') {
144
+ return originalReq.clone({
145
+ setHeaders: { Authorization: `Bearer ${newToken}` },
146
+ });
147
+ }
148
+ return originalReq.clone();
149
+ }
150
+ /**
151
+ * Class-based interceptor for NgModule compatibility.
152
+ */
153
+ export class AuthInterceptor {
154
+ intercept(req, next) {
155
+ return authInterceptor(req, next);
156
+ }
157
+ }
158
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5pbnRlcmNlcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3N0YW5kYWxvbmUvYXV0aC5pbnRlcmNlcHRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNwRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNwRCxPQUFPLEVBQWlELFVBQVUsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3BILE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzlGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFN0M7OztHQUdHO0FBQ0gsSUFBSSxZQUFZLEdBQUcsS0FBSyxDQUFDO0FBQ3pCLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxlQUFlLENBQWdCLElBQUksQ0FBQyxDQUFDO0FBRXJFOztHQUVHO0FBQ0gsTUFBTSxlQUFlLEdBQUcsSUFBSSxPQUFPLEVBQXdCLENBQUM7QUFFNUQ7O0dBRUc7QUFDSCxTQUFTLFlBQVksQ0FBQyxVQUFrQjtJQUN0QyxJQUFJLE9BQU8sUUFBUSxLQUFLLFdBQVc7UUFBRSxPQUFPLElBQUksQ0FBQztJQUNqRCxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxRQUFRLFVBQVUsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUM5RSxPQUFPLEtBQUssQ0FBQyxDQUFDLENBQUMsa0JBQWtCLENBQUMsS0FBSyxD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SSxRQUFRLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDbkUsT0FBTyxXQUFXLENBQUMsS0FBSyxDQUFDO1lBQ3ZCLFVBQVUsRUFBRSxFQUFFLGFBQWEsRUFBRSxVQUFVLFFBQVEsRUFBRSxFQUFFO1NBQ3BELENBQUMsQ0FBQztJQUNMLENBQUM7SUFDRCxPQUFPLFdBQVcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztBQUM3QixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8sZUFBZTtJQUMxQixTQUFTLENBQUMsR0FBeUIsRUFBRSxJQUFtQjtRQUN0RCxPQUFPLGVBQWUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDcEMsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaW5qZWN0LCBQTEFURk9STV9JRCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgaXNQbGF0Zm9ybUJyb3dzZXIgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgSHR0cEhhbmRsZXJGbiwgSHR0cEludGVyY2VwdG9yRm4sIEh0dHBSZXF1ZXN0LCBIdHRwQ2xpZW50LCBIdHRwRXJyb3JSZXNwb25zZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBjYXRjaEVycm9yLCBzd2l0Y2hNYXAsIHRocm93RXJyb3IsIGZpbHRlciwgdGFrZSwgQmVoYXZpb3JTdWJqZWN0LCBmcm9tIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBOQVVUSF9DTElFTlRfQ09ORklHIH0gZnJvbSAnLi90b2tlbnMnO1xuaW1wb3J0IHsgQXV0aFNlcnZpY2UgfSBmcm9tICcuL2F1dGguc2VydmljZSc7XG5cbi8qKlxuICogUmVmcmVzaCBzdGF0ZSBtYW5hZ2VtZW50LlxuICogQmVoYXZpb3JTdWJqZWN0IHBhdHRlcm4gaXMgdGhlIGluZHVzdHJ5LXN0YW5kYXJkIGZvciB0b2tlbiByZWZyZXNoLlxuICovXG5sZXQgaXNSZWZyZXNoaW5nID0gZmFsc2U7XG5jb25zdCByZWZyZXNoVG9rZW5TdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmcgfCBudWxsPihudWxsKTtcblxuLyoqXG4gKiBUcmFjayByZXRyaWVkIHJlcXVlc3RzIHRvIHByZXZlbnQgaW5maW5pdGUgbG9vcHMuXG4gKi9cbmNvbnN0IHJldHJpZWRSZXF1ZXN0cyA9IG5ldyBXZWFrU2V0PEh0dHBSZXF1ZXN0PHVua25vd24+PigpO1xuXG4vKipcbiAqIEdldCBDU1JGIHRva2VuIGZyb20gY29va2llLlxuICovXG5mdW5jdGlvbiBnZXRDc3JmVG9rZW4oY29va2llTmFtZTogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gIGlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICd1bmRlZmluZWQnKSByZXR1cm4gbnVsbDtcbiAgY29uc3QgbWF0Y2ggPSBkb2N1bWVudC5jb29raWUubWF0Y2gobmV3IFJlZ0V4cChgKF58ICkke2Nvb2tpZU5hbWV9PShbXjtdKylgKSk7XG4gIHJldHVybiBtYXRjaCA/IGRlY29kZVVSSUNvbXBvbmVudChtYXRjaFsyXSkgOiBudWxsO1xufVxuXG4vKipcbiAqIEFuZ3VsYXIgSFRUUCBpbnRlcmNlcHRvciBmb3IgbmF1dGgtdG9vbGtpdC5cbiAqXG4gKiBIYW5kbGVzOlxuICogLSBDb29raWVzIG1vZGU6IHdpdGhDcmVkZW50aWFscyArIENTUkYgdG9rZW5zICsgcmVmcmVzaCB2aWEgUE9TVFxuICogLSBKU09OIG1vZGU6IHJlZnJlc2ggdmlhIFNESywgcmV0cnkgd2l0aCBuZXcgdG9rZW5cbiAqL1xuZXhwb3J0IGNvbnN0IGF1dGhJbnRlcmNlcHRvcjogSHR0cEludGVyY2VwdG9yRm4gPSAocmVxOiBIdHRwUmVxdWVzdDx1bmtub3duPiwgbmV4dDogSHR0cEhhbmRsZXJGbikgPT4ge1xuICBjb25zdCBjb25maWcgPSBpbmplY3QoTkFVVEhfQ0xJRU5UX0NPTkZJRyk7XG4gIGNvbnN0IGh0dHAgPSBpbmplY3QoSHR0cENsaWVudCk7XG4gIGNvbnN0IGF1dGhTZXJ2aWNlID0gaW5qZWN0KEF1dGhTZXJ2aWNlKTtcbiAgY29uc3QgcGxhdGZvcm1JZCA9IGluamVjdChQTEFURk9STV9JRCk7XG4gIGNvbnN0IHJvdXRlciA9IGluamVjdChSb3V0ZXIpO1xuICBjb25zdCBpc0Jyb3dzZXIgPSBpc1BsYXRmb3JtQnJvd3NlcihwbGF0Zm9ybUlkKTtcblxuICBpZiAoIWlzQnJvd3Nlcikge1xuICAgIHJldHVybiBuZXh0KHJlcSk7XG4gIH1cblxuICBjb25zdCB0b2tlbkRlbGl2ZXJ5ID0gY29uZmlnLnRva2VuRGVsaXZlcnk7XG4gIGNvbnN0IGJhc2VVcmwgPSBjb25maWcuYmFzZVVybDtcbiAgY29uc3QgZW5kcG9pbnRzID0gY29uZmlnLmVuZHBvaW50cyA/PyB7fTtcbiAgY29uc3QgcmVmcmVzaFBhdGggPSBlbmRwb2ludHMucmVmcmVzaCA/PyAnL3JlZnJlc2gnO1xuICBjb25zdCBsb2dpblBhdGggPSBlbmRwb2ludHMubG9naW4gPz8gJy9sb2dpbic7XG4gIGNvbnN0IHNpZ251cFBhdGggPSBlbmRwb2ludHMuc2lnbnVwID8/ICcvc2lnbnVwJztcbiAgY29uc3Qgc29jaWFsRXhjaGFuZ2VQYXRoID0gZW5kcG9pbnRzLnNvY2lhbEV4Y2hhbmdlID8/ICcvc29jaWFsL2V4Y2hhbmdlJztcbiAgY29uc3QgcmVmcmVzaFVybCA9IGAke2Jhc2VVcmx9JHtyZWZyZXNoUGF0aH1gO1xuXG4gIGNvbnN0IGlzQXV0aEFwaVJlcXVlc3QgPSByZXEudXJsLmluY2x1ZGVzKGJhc2VVcmwpO1xuICBjb25zdCBpc1JlZnJlc2hFbmRwb2ludCA9IHJlcS51cmwuaW5jbHVkZXMocmVmcmVzaFBhdGgpO1xuICBjb25zdCBpc1B1YmxpY0VuZHBvaW50ID1cbiAgICByZXEudXJsLmluY2x1ZGVzKGxvZ2luUGF0aCkgfHwgcmVxLnVybC5pbmNsdWRlcyhzaWdudXBQYXRoKSB8fCByZXEudXJsLmluY2x1ZGVzKHNvY2lhbEV4Y2hhbmdlUGF0aCk7XG5cbiAgLy8gQnVpbGQgcmVxdWVzdCB3aXRoIGNyZWRlbnRpYWxzIChjb29raWVzIG1vZGUgb25seSlcbiAgbGV0IGF1dGhSZXEgPSByZXE7XG4gIGlmICh0b2tlbkRlbGl2ZXJ5ID09PSAnY29va2llcycpIHtcbiAgICBhdXRoUmVxID0gYXV0aFJlcS5jbG9uZSh7IHdpdGhDcmVkZW50aWFsczogdHJ1ZSB9KTtcblxuICAgIGlmIChbJ1BPU1QnLCAnUFVUJywgJ1BBVENIJywgJ0RFTEVURSddLmluY2x1ZGVzKHJlcS5tZXRob2QpKSB7XG4gICAgICBjb25zdCBjc3JmQ29va2llTmFtZSA9IGNvbmZpZy5jc3JmPy5jb29raWVOYW1lID8/ICduYXV0aF9jc3JmX3Rva2VuJztcbiAgICAgIGNvbnN0IGNzcmZIZWFkZXJOYW1lID0gY29uZmlnLmNzcmY/LmhlYWRlck5hbWUgPz8gJ3gtY3NyZi10b2tlbic7XG4gICAgICBjb25zdCBjc3JmVG9rZW4gPSBnZXRDc3JmVG9rZW4oY3NyZkNvb2tpZU5hbWUpO1xuICAgICAgaWYgKGNzcmZUb2tlbikge1xuICAgICAgICBhdXRoUmVxID0gYXV0aFJlcS5jbG9uZSh7IHNldEhlYWRlcnM6IHsgW2NzcmZIZWFkZXJOYW1lXTogY3NyZlRva2VuIH0gfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5leHQoYXV0aFJlcSkucGlwZShcbiAgICBjYXRjaEVycm9yKChlcnJvcjogdW5rbm93bikgPT4ge1xuICAgICAgY29uc3Qgc2hvdWxkSGFuZGxlID1cbiAgICAgICAgZXJyb3IgaW5zdGFuY2VvZiBIdHRwRXJyb3JSZXNwb25zZSAmJlxuICAgICAgICBlcnJvci5zdGF0dXMgPT09IDQwMSAmJlxuICAgICAgICBpc0F1dGhBcGlSZXF1ZXN0ICYmXG4gICAgICAgICFpc1JlZnJlc2hFbmRwb2ludCAmJlxuICAgICAgICAhaXNQdWJsaWNFbmRwb2ludCAmJlxuICAgICAgICAhcmV0cmllZFJlcXVlc3RzLmhhcyhyZXEpO1xuXG4gICAgICBpZiAoIXNob3VsZEhhbmRsZSkge1xuICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XG4gICAgICB9XG5cbiAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdbbmF1dGgtaW50ZXJjZXB0b3JdIDQwMSBkZXRlY3RlZDonLCByZXEudXJsKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFpc1JlZnJlc2hpbmcpIHtcbiAgICAgICAgaXNSZWZyZXNoaW5nID0gdHJ1ZTtcbiAgICAgICAgcmVmcmVzaFRva2VuU3ViamVjdC5uZXh0KG51bGwpO1xuXG4gICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJ1tuYXV0aC1pbnRlcmNlcHRvcl0gU3RhcnRpbmcgcmVmcmVzaC4uLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVmcmVzaCBiYXNlZCBvbiBtb2RlXG4gICAgICAgIGNvbnN0IHJlZnJlc2gkID1cbiAgICAgICAgICB0b2tlbkRlbGl2ZXJ5ID09PSAnY29va2llcydcbiAgICAgICAgICAgID8gaHR0cC5wb3N0PHsgYWNjZXNzVG9rZW4/OiBzdHJpbmcgfT4ocmVmcmVzaFVybCwge30sIHsgd2l0aENyZWRlbnRpYWxzOiB0cnVlIH0pXG4gICAgICAgICAgICA6IGZyb20oYXV0aFNlcnZpY2UucmVmcmVzaCgpKTtcblxuICAgICAgICByZXR1cm4gcmVmcmVzaCQucGlwZShcbiAgICAgICAgICBzd2l0Y2hNYXAoKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUud2FybignW25hdXRoLWludGVyY2VwdG9yXSBSZWZyZXNoIHN1Y2Nlc3NmdWwnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlzUmVmcmVzaGluZyA9IGZhbHNlO1xuXG4gICAgICAgICAgICAvLyBHZXQgbmV3IHRva2VuIChKU09OIG1vZGUpIG9yIHNpZ25hbCBzdWNjZXNzIChjb29raWVzIG1vZGUpXG4gICAgICAgICAgICBjb25zdCBuZXdUb2tlbiA9ICdhY2Nlc3NUb2tlbicgaW4gcmVzcG9uc2UgPyByZXNwb25zZS5hY2Nlc3NUb2tlbiA6ICdzdWNjZXNzJztcbiAgICAgICAgICAgIHJlZnJlc2hUb2tlblN1YmplY3QubmV4dChuZXdUb2tlbiA/PyAnc3VjY2VzcycpO1xuXG4gICAgICAgICAgICAvLyBCdWlsZCByZXRyeSByZXF1ZXN0XG4gICAgICAgICAgICBjb25zdCByZXRyeVJlcSA9IGJ1aWxkUmV0cnlSZXF1ZXN0KGF1dGhSZXEsIHRva2VuRGVsaXZlcnksIG5ld1Rva2VuKTtcbiAgICAgICAgICAgIHJldHJpZWRSZXF1ZXN0cy5hZGQocmV0cnlSZXEpO1xuXG4gICAgICAgICAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUud2FybignW25hdXRoLWludGVyY2VwdG9yXSBSZXRyeWluZzonLCByZXEudXJsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXh0KHJldHJ5UmVxKTtcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBjYXRjaEVycm9yKChlcnIpID0+IHtcbiAgICAgICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignW25hdXRoLWludGVyY2VwdG9yXSBSZWZyZXNoIGZhaWxlZDonLCBlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaXNSZWZyZXNoaW5nID0gZmFsc2U7XG4gICAgICAgICAgICByZWZyZXNoVG9rZW5TdWJqZWN0Lm5leHQobnVsbCk7XG5cbiAgICAgICAgICAgIC8vIEhhbmRsZSBzZXNzaW9uIGV4cGlyYXRpb24gLSByZWRpcmVjdCB0byBjb25maWd1cmVkIFVSTFxuICAgICAgICAgICAgaWYgKGNvbmZpZy5yZWRpcmVjdHM/LnNlc3Npb25FeHBpcmVkKSB7XG4gICAgICAgICAgICAgIHJvdXRlci5uYXZpZ2F0ZUJ5VXJsKGNvbmZpZy5yZWRpcmVjdHMuc2Vzc2lvbkV4cGlyZWQpLmNhdGNoKChuYXZFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1tuYXV0aC1pbnRlcmNlcHRvcl0gTmF2aWdhdGlvbiBmYWlsZWQ6JywgbmF2RXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGVycik7XG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBXYWl0IGZvciBvbmdvaW5nIHJlZnJlc2hcbiAgICAgICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgICAgIGNvbnNvbGUud2FybignW25hdXRoLWludGVyY2VwdG9yXSBXYWl0aW5nIGZvciByZWZyZXNoLi4uJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlZnJlc2hUb2tlblN1YmplY3QucGlwZShcbiAgICAgICAgICBmaWx0ZXIoKHRva2VuKTogdG9rZW4gaXMgc3RyaW5nID0+IHRva2VuICE9PSBudWxsKSxcbiAgICAgICAgICB0YWtlKDEpLFxuICAgICAgICAgIHN3aXRjaE1hcCgodG9rZW4pID0+IHtcbiAgICAgICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdbbmF1dGgtaW50ZXJjZXB0b3JdIFJlZnJlc2ggZG9uZSwgcmV0cnlpbmc6JywgcmVxLnVybCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXRyeVJlcSA9IGJ1aWxkUmV0cnlSZXF1ZXN0KGF1dGhSZXEsIHRva2VuRGVsaXZlcnksIHRva2VuKTtcbiAgICAgICAgICAgIHJldHJpZWRSZXF1ZXN0cy5hZGQocmV0cnlSZXEpO1xuICAgICAgICAgICAgcmV0dXJuIG5leHQocmV0cnlSZXEpO1xuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0pLFxuICApO1xufTtcblxuLyoqXG4gKiBCdWlsZCByZXRyeSByZXF1ZXN0IHdpdGggYXBwcm9wcmlhdGUgYXV0aC5cbiAqL1xuZnVuY3Rpb24gYnVpbGRSZXRyeVJlcXVlc3QoXG4gIG9yaWdpbmFsUmVxOiBIdHRwUmVxdWVzdDx1bmtub3duPixcbiAgdG9rZW5EZWxpdmVyeTogc3RyaW5nLFxuICBuZXdUb2tlbj86IHN0cmluZyxcbik6IEh0dHBSZXF1ZXN0PHVua25vd24+IHtcbiAgaWYgKHRva2VuRGVsaXZlcnkgPT09ICdqc29uJyAmJiBuZXdUb2tlbiAmJiBuZXdUb2tlbiAhPT0gJ3N1Y2Nlc3MnKSB7XG4gICAgcmV0dXJuIG9yaWdpbmFsUmVxLmNsb25lKHtcbiAgICAgIHNldEhlYWRlcnM6IHsgQXV0aG9yaXphdGlvbjogYEJlYXJlciAke25ld1Rva2VufWAgfSxcbiAgICB9KTtcbiAgfVxuICByZXR1cm4gb3JpZ2luYWxSZXEuY2xvbmUoKTtcbn1cblxuLyoqXG4gKiBDbGFzcy1iYXNlZCBpbnRlcmNlcHRvciBmb3IgTmdNb2R1bGUgY29tcGF0aWJpbGl0eS5cbiAqL1xuZXhwb3J0IGNsYXNzIEF1dGhJbnRlcmNlcHRvciB7XG4gIGludGVyY2VwdChyZXE6IEh0dHBSZXF1ZXN0PHVua25vd24+LCBuZXh0OiBIdHRwSGFuZGxlckZuKSB7XG4gICAgcmV0dXJuIGF1dGhJbnRlcmNlcHRvcihyZXEsIG5leHQpO1xuICB9XG59XG4iXX0=