@dontdrinkandroot/ngx-extensions 0.0.5 → 0.2.0

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 (70) hide show
  1. package/{esm2015/dontdrinkandroot-ngx-extensions.js → esm2020/dontdrinkandroot-ngx-extensions.mjs} +1 -1
  2. package/esm2020/public-api.mjs +24 -0
  3. package/esm2020/src/cookie/cookie.service.mjs +135 -0
  4. package/esm2020/src/ddr-extensions.module.mjs +40 -0
  5. package/esm2020/src/http/redirect-to-login-interceptor.service.mjs +35 -0
  6. package/esm2020/src/http/url-info.mjs +26 -0
  7. package/esm2020/src/http/with-credentials-interceptor.service.mjs +19 -0
  8. package/esm2020/src/image/lazy-image.directive.mjs +132 -0
  9. package/esm2020/src/jwt/jwt-interceptor.service.mjs +26 -0
  10. package/esm2020/src/jwt/jwt-refresh-token-interceptor.service.mjs +50 -0
  11. package/esm2020/src/jwt/jwt-token-response.mjs +2 -0
  12. package/esm2020/src/jwt/jwt.service.mjs +82 -0
  13. package/esm2020/src/methoddecorator/debounce.mjs +13 -0
  14. package/esm2020/src/methoddecorator/limit.mjs +16 -0
  15. package/esm2020/src/scroll/bottom-hit.directive.mjs +60 -0
  16. package/esm2020/src/scroll/scroll.service.mjs +38 -0
  17. package/esm2020/src/util/collection-utils.mjs +27 -0
  18. package/esm2020/src/util/number-utils.mjs +10 -0
  19. package/esm2020/src/util/object-utils.mjs +9 -0
  20. package/esm2020/src/util/string-utils.mjs +35 -0
  21. package/esm2020/src/util/type-utils.mjs +9 -0
  22. package/esm2020/src/visibility/visibility.service.mjs +19 -0
  23. package/fesm2015/dontdrinkandroot-ngx-extensions.mjs +760 -0
  24. package/fesm2015/dontdrinkandroot-ngx-extensions.mjs.map +1 -0
  25. package/{fesm2015/dontdrinkandroot-ngx-extensions.js → fesm2020/dontdrinkandroot-ngx-extensions.mjs} +210 -154
  26. package/fesm2020/dontdrinkandroot-ngx-extensions.mjs.map +1 -0
  27. package/{dontdrinkandroot-ngx-extensions.d.ts → index.d.ts} +1 -0
  28. package/package.json +23 -11
  29. package/public-api.d.ts +1 -0
  30. package/src/cookie/cookie.service.d.ts +5 -2
  31. package/src/ddr-extensions.module.d.ts +6 -0
  32. package/src/http/redirect-to-login-interceptor.service.d.ts +4 -1
  33. package/src/http/url-info.d.ts +8 -7
  34. package/src/http/with-credentials-interceptor.service.d.ts +3 -0
  35. package/src/image/lazy-image.directive.d.ts +4 -1
  36. package/src/jwt/jwt-interceptor.service.d.ts +3 -0
  37. package/src/jwt/jwt-refresh-token-interceptor.service.d.ts +3 -0
  38. package/src/jwt/jwt.service.d.ts +3 -0
  39. package/src/scroll/bottom-hit.directive.d.ts +3 -0
  40. package/src/scroll/scroll.service.d.ts +3 -0
  41. package/src/util/collection-utils.d.ts +2 -4
  42. package/src/util/object-utils.d.ts +1 -0
  43. package/src/util/type-utils.d.ts +3 -0
  44. package/src/visibility/visibility.service.d.ts +3 -0
  45. package/bundles/dontdrinkandroot-ngx-extensions.umd.js +0 -1088
  46. package/bundles/dontdrinkandroot-ngx-extensions.umd.js.map +0 -1
  47. package/bundles/dontdrinkandroot-ngx-extensions.umd.min.js +0 -16
  48. package/bundles/dontdrinkandroot-ngx-extensions.umd.min.js.map +0 -1
  49. package/dontdrinkandroot-ngx-extensions.metadata.json +0 -1
  50. package/esm2015/public-api.js +0 -23
  51. package/esm2015/src/cookie/cookie.service.js +0 -136
  52. package/esm2015/src/ddr-extensions.module.js +0 -28
  53. package/esm2015/src/http/redirect-to-login-interceptor.service.js +0 -33
  54. package/esm2015/src/http/url-info.js +0 -26
  55. package/esm2015/src/http/with-credentials-interceptor.service.js +0 -16
  56. package/esm2015/src/image/lazy-image.directive.js +0 -118
  57. package/esm2015/src/jwt/jwt-interceptor.service.js +0 -26
  58. package/esm2015/src/jwt/jwt-refresh-token-interceptor.service.js +0 -50
  59. package/esm2015/src/jwt/jwt-token-response.js +0 -2
  60. package/esm2015/src/jwt/jwt.service.js +0 -73
  61. package/esm2015/src/methoddecorator/debounce.js +0 -12
  62. package/esm2015/src/methoddecorator/limit.js +0 -16
  63. package/esm2015/src/scroll/bottom-hit.directive.js +0 -53
  64. package/esm2015/src/scroll/scroll.service.js +0 -39
  65. package/esm2015/src/util/collection-utils.js +0 -29
  66. package/esm2015/src/util/number-utils.js +0 -10
  67. package/esm2015/src/util/object-utils.js +0 -6
  68. package/esm2015/src/util/string-utils.js +0 -35
  69. package/esm2015/src/visibility/visibility.service.js +0 -18
  70. package/fesm2015/dontdrinkandroot-ngx-extensions.js.map +0 -1
@@ -0,0 +1,760 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Directive, Input, HostBinding, HostListener, EventEmitter, Output, InjectionToken, NgModule, Injectable, Inject } from '@angular/core';
3
+ import { __decorate } from 'tslib';
4
+ import * as i2 from '@angular/common';
5
+ import { DOCUMENT } from '@angular/common';
6
+ import * as i1 from '@angular/router';
7
+ import { NavigationStart } from '@angular/router';
8
+ import { merge, fromEvent, throwError } from 'rxjs';
9
+ import { debounceTime, startWith, map, distinctUntilChanged, shareReplay, catchError, switchMap } from 'rxjs/operators';
10
+ import * as i2$1 from '@angular/common/http';
11
+ import { HttpErrorResponse } from '@angular/common/http';
12
+
13
+ class NumberUtils {
14
+ static getNextPowerOfTwo(value) {
15
+ let target = 2;
16
+ while (target < value) {
17
+ target *= 2;
18
+ }
19
+ return target;
20
+ }
21
+ }
22
+
23
+ class StringUtils {
24
+ static capitalizeFirstLetter(text) {
25
+ return text.charAt(0).toUpperCase() + text.slice(1);
26
+ }
27
+ static stripTrailingSlash(text) {
28
+ const lastChar = text.charAt(text.length - 1);
29
+ if ('/' === lastChar) {
30
+ return text.slice(0, text.length - 1);
31
+ }
32
+ return text;
33
+ }
34
+ static updateUrlParameter(uri, key, value) {
35
+ // remove the hash part before operating on the uri
36
+ const i = uri.indexOf('#');
37
+ const hash = i === -1 ? '' : uri.substr(i);
38
+ uri = i === -1 ? uri : uri.substr(0, i);
39
+ const re = new RegExp('([?&])' + key + '=.*?(&|$)', 'i');
40
+ const separator = uri.indexOf('?') !== -1 ? '&' : '?';
41
+ if (uri.match(re)) {
42
+ uri = uri.replace(re, '$1' + key + '=' + value + '$2');
43
+ }
44
+ else {
45
+ uri = uri + separator + key + '=' + value;
46
+ }
47
+ return uri + hash; // finally append the hash as well
48
+ }
49
+ static createRandomString(lengthOfCode, possible) {
50
+ let text = '';
51
+ for (let i = 0; i < lengthOfCode; i++) {
52
+ text += possible.charAt(Math.floor(Math.random() * possible.length));
53
+ }
54
+ return text;
55
+ }
56
+ }
57
+
58
+ function Debounce(delay = 250) {
59
+ let timeoutReference = undefined;
60
+ return (target, propertyKey, descriptor) => {
61
+ const original = descriptor.value;
62
+ descriptor.value = function (...args) {
63
+ if (null != timeoutReference)
64
+ clearTimeout(timeoutReference);
65
+ timeoutReference = setTimeout(() => original.apply(this, args), delay);
66
+ };
67
+ return descriptor;
68
+ };
69
+ }
70
+
71
+ function Limit(rate = 250) {
72
+ let timeoutReference = undefined;
73
+ return (target, propertyKey, descriptor) => {
74
+ const original = descriptor.value;
75
+ descriptor.value = function (...args) {
76
+ if (null == timeoutReference) {
77
+ timeoutReference = setTimeout(() => {
78
+ original.apply(this, args);
79
+ timeoutReference = undefined;
80
+ }, rate);
81
+ }
82
+ };
83
+ return descriptor;
84
+ };
85
+ }
86
+
87
+ class LazyImageDirective {
88
+ constructor(element, changeDetectorRef) {
89
+ this.element = element;
90
+ this.changeDetectorRef = changeDetectorRef;
91
+ this.objectFit = 'contain';
92
+ this.offset = 1000;
93
+ this.hostSrc = 'assets/placeholder.gif';
94
+ this.hostStyleObjectFit = 'contain';
95
+ this.displayed = false;
96
+ this.maxLoadedDimension = null;
97
+ }
98
+ windowResized($event) {
99
+ this.displayed = false;
100
+ this.check();
101
+ }
102
+ windowScroll($event) {
103
+ this.check();
104
+ }
105
+ /**
106
+ * @override
107
+ */
108
+ ngOnChanges(changes) {
109
+ this.displayed = false;
110
+ this.maxLoadedDimension = null;
111
+ this.check();
112
+ }
113
+ check() {
114
+ if (this.element.nativeElement.parentElement.offsetWidth > 0) {
115
+ this.doCheck();
116
+ }
117
+ else {
118
+ setTimeout(() => this.doCheck(), 1);
119
+ }
120
+ }
121
+ doCheck() {
122
+ if (this.displayed || this.isHidden(this.element.nativeElement)) {
123
+ return;
124
+ }
125
+ if (this.isInsideViewport(this.element.nativeElement, this.offset)) {
126
+ this.displayed = true;
127
+ const dimension = this.getDimension();
128
+ this.hostStyleWidthPx = dimension.width;
129
+ this.hostStyleHeightPx = dimension.height;
130
+ if (this.maxLoadedDimension != null
131
+ && this.maxLoadedDimension.width >= dimension.width
132
+ && this.maxLoadedDimension.height >= dimension.height) {
133
+ // console.log('has smaller dimension');
134
+ return;
135
+ }
136
+ this.maxLoadedDimension = dimension;
137
+ let wantedSize;
138
+ if (this.objectFit === 'cover') {
139
+ wantedSize = NumberUtils.getNextPowerOfTwo(Math.max(dimension.width, dimension.height));
140
+ this.hostStyleObjectFit = 'cover';
141
+ }
142
+ else {
143
+ wantedSize = NumberUtils.getNextPowerOfTwo(Math.min(dimension.width, dimension.height));
144
+ this.hostStyleObjectFit = 'contain';
145
+ }
146
+ this.hostSrc = StringUtils.updateUrlParameter(this.src, 'size', String(wantedSize));
147
+ this.changeDetectorRef.markForCheck();
148
+ }
149
+ }
150
+ isInsideViewport(element, threshold) {
151
+ const ownerDocument = element.ownerDocument;
152
+ const documentTop = window.pageYOffset || ownerDocument.body.scrollTop;
153
+ const documentLeft = window.pageXOffset || ownerDocument.body.scrollLeft;
154
+ const documentWidth = window.innerWidth || (ownerDocument.documentElement.clientWidth || document.body.clientWidth);
155
+ const documentHeight = window.innerHeight || (ownerDocument.documentElement.clientHeight || document.body.clientHeight);
156
+ const topOffset = element.getBoundingClientRect().top + documentTop - ownerDocument.documentElement.clientTop;
157
+ const leftOffset = element.getBoundingClientRect().left + documentLeft - ownerDocument.documentElement.clientLeft;
158
+ const isBelowViewport = documentHeight + documentTop <= topOffset - threshold;
159
+ const isAtRightOfViewport = documentWidth + window.pageXOffset <= leftOffset - threshold;
160
+ const isAboveViewport = documentTop >= topOffset + threshold + element.offsetHeight;
161
+ const isAtLeftOfViewport = documentLeft >= leftOffset + threshold + element.offsetWidth;
162
+ return !isBelowViewport && !isAboveViewport && !isAtRightOfViewport && !isAtLeftOfViewport;
163
+ }
164
+ getDimension() {
165
+ return {
166
+ width: this.element.nativeElement.parentElement.offsetWidth,
167
+ height: this.element.nativeElement.parentElement.offsetHeight,
168
+ };
169
+ }
170
+ isHidden(element) {
171
+ return window.getComputedStyle(element).display === 'none';
172
+ }
173
+ }
174
+ LazyImageDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: LazyImageDirective, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
175
+ LazyImageDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.2", type: LazyImageDirective, selector: "[ddrLazyImage]", inputs: { src: ["ddrLazyImage", "src"], objectFit: "objectFit", offset: "offset" }, host: { listeners: { "window:resize": "windowResized($event)", "window:scroll": "windowScroll($event)" }, properties: { "src": "this.hostSrc", "style.width.px": "this.hostStyleWidthPx", "style.height.px": "this.hostStyleHeightPx", "style.object-fit": "this.hostStyleObjectFit" } }, usesOnChanges: true, ngImport: i0 });
176
+ __decorate([
177
+ Debounce()
178
+ ], LazyImageDirective.prototype, "windowResized", null);
179
+ __decorate([
180
+ Limit()
181
+ ], LazyImageDirective.prototype, "windowScroll", null);
182
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: LazyImageDirective, decorators: [{
183
+ type: Directive,
184
+ args: [{ selector: '[ddrLazyImage]' }]
185
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { src: [{
186
+ type: Input,
187
+ args: ['ddrLazyImage']
188
+ }], objectFit: [{
189
+ type: Input
190
+ }], offset: [{
191
+ type: Input
192
+ }], hostSrc: [{
193
+ type: HostBinding,
194
+ args: ['src']
195
+ }], hostStyleWidthPx: [{
196
+ type: HostBinding,
197
+ args: ['style.width.px']
198
+ }], hostStyleHeightPx: [{
199
+ type: HostBinding,
200
+ args: ['style.height.px']
201
+ }], hostStyleObjectFit: [{
202
+ type: HostBinding,
203
+ args: ['style.object-fit']
204
+ }], windowResized: [{
205
+ type: HostListener,
206
+ args: ['window:resize', ['$event']]
207
+ }], windowScroll: [{
208
+ type: HostListener,
209
+ args: ['window:scroll', ['$event']]
210
+ }] } });
211
+
212
+ class BottomHitDirective {
213
+ constructor() {
214
+ this.offset = 1000;
215
+ this.onWindowBottomHit = new EventEmitter();
216
+ this.onElementBottomHit = new EventEmitter();
217
+ }
218
+ scrolled($event) {
219
+ this.elementScrollEvent($event);
220
+ }
221
+ windowScrolled($event) {
222
+ this.windowScrollEvent($event);
223
+ }
224
+ windowScrollEvent($event) {
225
+ const pageHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.body.clientHeight, document.documentElement.clientHeight);
226
+ const viewportHeight = document.documentElement.clientHeight;
227
+ const scrollPosition = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
228
+ const distanceToBottom = pageHeight - (scrollPosition + viewportHeight);
229
+ if (distanceToBottom < this.offset) {
230
+ this.onWindowBottomHit.emit();
231
+ }
232
+ }
233
+ elementScrollEvent($event) {
234
+ const target = $event.target;
235
+ const scrollPosition = target.scrollHeight - target.scrollTop;
236
+ const offsetHeight = target.offsetHeight;
237
+ const isReachingBottom = (scrollPosition - offsetHeight) < this.offset;
238
+ if (isReachingBottom) {
239
+ this.onElementBottomHit.emit();
240
+ }
241
+ }
242
+ }
243
+ BottomHitDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: BottomHitDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
244
+ BottomHitDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.2", type: BottomHitDirective, selector: "[ddrBottomHit]", outputs: { onWindowBottomHit: "onWindowBottomHit", onElementBottomHit: "onElementBottomHit" }, host: { listeners: { "scroll": "scrolled($event)", "window:scroll": "windowScrolled($event)" } }, ngImport: i0 });
245
+ __decorate([
246
+ Limit()
247
+ ], BottomHitDirective.prototype, "scrolled", null);
248
+ __decorate([
249
+ Limit()
250
+ ], BottomHitDirective.prototype, "windowScrolled", null);
251
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: BottomHitDirective, decorators: [{
252
+ type: Directive,
253
+ args: [{
254
+ selector: '[ddrBottomHit]'
255
+ }]
256
+ }], ctorParameters: function () { return []; }, propDecorators: { onWindowBottomHit: [{
257
+ type: Output
258
+ }], onElementBottomHit: [{
259
+ type: Output
260
+ }], scrolled: [{
261
+ type: HostListener,
262
+ args: ['scroll', ['$event']]
263
+ }], windowScrolled: [{
264
+ type: HostListener,
265
+ args: ['window:scroll', ['$event']]
266
+ }] } });
267
+
268
+ const DDR_STORAGE_PREFIX = new InjectionToken('DDR_STORAGE_PREFIX');
269
+ const DDR_JWT_REFRESH_TOKEN_URL = new InjectionToken('DDR_JWT_REFRESH_TOKEN_URL');
270
+ const DDR_LOGIN_PATH = new InjectionToken('DDR_LOGIN_PATH');
271
+ class DdrExtensionsModule {
272
+ }
273
+ DdrExtensionsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: DdrExtensionsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
274
+ DdrExtensionsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.2", ngImport: i0, type: DdrExtensionsModule, declarations: [LazyImageDirective,
275
+ BottomHitDirective], exports: [LazyImageDirective,
276
+ BottomHitDirective] });
277
+ DdrExtensionsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: DdrExtensionsModule, providers: [
278
+ {
279
+ provide: DDR_LOGIN_PATH,
280
+ useValue: '/login'
281
+ }
282
+ ] });
283
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: DdrExtensionsModule, decorators: [{
284
+ type: NgModule,
285
+ args: [{
286
+ declarations: [
287
+ LazyImageDirective,
288
+ BottomHitDirective
289
+ ],
290
+ imports: [],
291
+ providers: [
292
+ {
293
+ provide: DDR_LOGIN_PATH,
294
+ useValue: '/login'
295
+ }
296
+ ],
297
+ exports: [
298
+ LazyImageDirective,
299
+ BottomHitDirective
300
+ ]
301
+ }]
302
+ }] });
303
+
304
+ // This service is based on the `ng2-cookies` package which sadly is not a service and does
305
+ class CookieService {
306
+ constructor(document) {
307
+ this.document = document;
308
+ // To avoid issues with server side prerendering, check if `document` is defined.
309
+ this.documentIsAccessible = document !== undefined;
310
+ }
311
+ /**
312
+ * @param name Cookie name
313
+ */
314
+ check(name) {
315
+ if (!this.documentIsAccessible) {
316
+ return false;
317
+ }
318
+ name = encodeURIComponent(name);
319
+ const regExp = this.getCookieRegExp(name);
320
+ return regExp.test(this.document.cookie);
321
+ }
322
+ /**
323
+ * @param name Cookie name
324
+ */
325
+ get(name) {
326
+ if (this.documentIsAccessible && this.check(name)) {
327
+ name = encodeURIComponent(name);
328
+ const regExp = this.getCookieRegExp(name);
329
+ const result = regExp.exec(this.document.cookie);
330
+ if (null == result)
331
+ return '';
332
+ return decodeURIComponent(result[1]);
333
+ }
334
+ else {
335
+ return '';
336
+ }
337
+ }
338
+ getAll() {
339
+ if (!this.documentIsAccessible) {
340
+ return {};
341
+ }
342
+ const cookies = {};
343
+ const document = this.document;
344
+ if (document.cookie && document.cookie !== '') {
345
+ const split = document.cookie.split(';');
346
+ for (let i = 0; i < split.length; i += 1) {
347
+ const currentCookie = split[i].split('=');
348
+ currentCookie[0] = currentCookie[0].replace(/^ /, '');
349
+ // @ts-ignore
350
+ cookies[decodeURIComponent(currentCookie[0])] = decodeURIComponent(currentCookie[1]);
351
+ }
352
+ }
353
+ return cookies;
354
+ }
355
+ /**
356
+ * @param name Cookie name
357
+ * @param value Cookie value
358
+ * @param expires Number of days until the cookies expires or an actual `Date`
359
+ * @param path Cookie path
360
+ * @param domain Cookie domain
361
+ * @param secure Secure flag
362
+ */
363
+ set(name, value, expires, path, domain, secure) {
364
+ if (!this.documentIsAccessible) {
365
+ return;
366
+ }
367
+ let cookieString = encodeURIComponent(name) + '=' + encodeURIComponent(value) + ';';
368
+ if (expires) {
369
+ if (typeof expires === 'number') {
370
+ const dateExpires = new Date(new Date().getTime() + expires * 1000 * 60 * 60 * 24);
371
+ cookieString += 'expires=' + dateExpires.toUTCString() + ';';
372
+ }
373
+ else {
374
+ cookieString += 'expires=' + expires.toUTCString() + ';';
375
+ }
376
+ }
377
+ if (path) {
378
+ cookieString += 'path=' + path + ';';
379
+ }
380
+ if (domain) {
381
+ cookieString += 'domain=' + domain + ';';
382
+ }
383
+ if (secure) {
384
+ cookieString += 'secure;';
385
+ }
386
+ this.document.cookie = cookieString;
387
+ }
388
+ /**
389
+ * @param name Cookie name
390
+ * @param path Cookie path
391
+ * @param domain Cookie domain
392
+ */
393
+ delete(name, path, domain) {
394
+ if (!this.documentIsAccessible) {
395
+ return;
396
+ }
397
+ this.set(name, '', -1, path, domain);
398
+ }
399
+ /**
400
+ * @param path Cookie path
401
+ * @param domain Cookie domain
402
+ */
403
+ deleteAll(path, domain) {
404
+ if (!this.documentIsAccessible) {
405
+ return;
406
+ }
407
+ const cookies = this.getAll();
408
+ for (const cookieName in cookies) {
409
+ if (cookies.hasOwnProperty(cookieName)) {
410
+ this.delete(cookieName, path, domain);
411
+ }
412
+ }
413
+ }
414
+ /**
415
+ * @param name Cookie name
416
+ */
417
+ getCookieRegExp(name) {
418
+ const escapedName = name.replace(/([\[\]{}()|=;+?,.*^$])/ig, '\\$1');
419
+ return new RegExp('(?:^' + escapedName + '|;\\s*' + escapedName + ')=(.*?)(?:;|$)', 'g');
420
+ }
421
+ }
422
+ CookieService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: CookieService, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
423
+ CookieService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: CookieService, providedIn: 'root' });
424
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: CookieService, decorators: [{
425
+ type: Injectable,
426
+ args: [{
427
+ providedIn: 'root'
428
+ }]
429
+ }], ctorParameters: function () {
430
+ return [{ type: Document, decorators: [{
431
+ type: Inject,
432
+ args: [DOCUMENT]
433
+ }] }];
434
+ } });
435
+
436
+ class ObjectUtils {
437
+ static deepCopy(value) {
438
+ return JSON.parse(JSON.stringify(value));
439
+ }
440
+ static getProperty(o, propertyName) {
441
+ return o[propertyName];
442
+ }
443
+ }
444
+
445
+ class CollectionUtils {
446
+ /**
447
+ * Maps an array into a Map by a specific property which should be unique.
448
+ */
449
+ static mapByProperty(entries, property) {
450
+ const map = new Map();
451
+ for (const entry of entries) {
452
+ map.set(ObjectUtils.getProperty(entry, property), entry);
453
+ }
454
+ return map;
455
+ }
456
+ /**
457
+ * Maps an array into a Map by a specified property and aggregates them into an array.
458
+ */
459
+ static mapArrayByProperty(entries, property) {
460
+ var _a;
461
+ const map = new Map();
462
+ for (const entry of entries) {
463
+ const value = ObjectUtils.getProperty(entry, property);
464
+ const existingEntries = (_a = map.get(value)) !== null && _a !== void 0 ? _a : [];
465
+ existingEntries.push(entry);
466
+ map.set(value, existingEntries);
467
+ }
468
+ return map;
469
+ }
470
+ }
471
+
472
+ class TypeUtils {
473
+ static notNull(value, message = 'Value must not be null') {
474
+ if (null == value) {
475
+ throw new Error(message);
476
+ }
477
+ return value;
478
+ }
479
+ }
480
+
481
+ class ScrollService {
482
+ constructor(router, viewportScroller) {
483
+ this.router = router;
484
+ this.viewportScroller = viewportScroller;
485
+ this.scrollPositionMap = new Map();
486
+ this.router.events
487
+ .subscribe(e => {
488
+ if (e instanceof NavigationStart) {
489
+ this.scrollPositionMap.set(this.router.url, this.viewportScroller.getScrollPosition());
490
+ }
491
+ });
492
+ }
493
+ restore() {
494
+ const url = this.router.url;
495
+ if (this.scrollPositionMap.has(url)) {
496
+ /* Restore after timeout so rendering was completed */
497
+ setTimeout(() => {
498
+ let scrollPosition = this.scrollPositionMap.get(url);
499
+ if (null != scrollPosition)
500
+ this.viewportScroller.scrollToPosition(scrollPosition);
501
+ }, 1);
502
+ }
503
+ }
504
+ }
505
+ ScrollService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: ScrollService, deps: [{ token: i1.Router }, { token: i2.ViewportScroller }], target: i0.ɵɵFactoryTarget.Injectable });
506
+ ScrollService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: ScrollService, providedIn: 'root' });
507
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: ScrollService, decorators: [{
508
+ type: Injectable,
509
+ args: [{
510
+ providedIn: 'root'
511
+ }]
512
+ }], ctorParameters: function () { return [{ type: i1.Router }, { type: i2.ViewportScroller }]; } });
513
+
514
+ class VisibilityService {
515
+ constructor() {
516
+ this.visibility$ = merge(fromEvent(document, 'visibilitychange'), fromEvent(window, 'focus'), fromEvent(window, 'blur')).pipe(debounceTime(50), startWith(true), map(() => document.hasFocus()), distinctUntilChanged(), shareReplay(1));
517
+ }
518
+ getVisibilityObservable() {
519
+ return this.visibility$;
520
+ }
521
+ }
522
+ VisibilityService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: VisibilityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
523
+ VisibilityService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: VisibilityService, providedIn: 'root' });
524
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: VisibilityService, decorators: [{
525
+ type: Injectable,
526
+ args: [{ providedIn: 'root' }]
527
+ }], ctorParameters: function () { return []; } });
528
+
529
+ class WithCredentialsInterceptor {
530
+ /**
531
+ * @override
532
+ */
533
+ intercept(req, next) {
534
+ const cloned = req.clone({
535
+ withCredentials: true
536
+ });
537
+ return next.handle(cloned);
538
+ }
539
+ }
540
+ WithCredentialsInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: WithCredentialsInterceptor, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
541
+ WithCredentialsInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: WithCredentialsInterceptor });
542
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: WithCredentialsInterceptor, decorators: [{
543
+ type: Injectable
544
+ }] });
545
+
546
+ class UrlInfo {
547
+ constructor(protocol, host, hostname, port, pathname, hash, search) {
548
+ this.protocol = protocol;
549
+ this.host = host;
550
+ this.hostname = hostname;
551
+ this.port = port;
552
+ this.pathname = pathname;
553
+ this.hash = hash;
554
+ this.search = search;
555
+ }
556
+ static parse(urlString) {
557
+ const parser = document.createElement('a');
558
+ parser.href = urlString;
559
+ return new UrlInfo(parser.protocol, parser.host, parser.hostname, parser.port === '' ? 80 : +parser.port, parser.pathname, parser.hash, parser.search);
560
+ }
561
+ getRoot() {
562
+ let root = this.protocol + '//' + this.hostname;
563
+ if (this.port !== 80)
564
+ root += ':' + this.port;
565
+ return root;
566
+ }
567
+ getUrl() {
568
+ return this.getRoot() + this.pathname;
569
+ }
570
+ }
571
+
572
+ class RedirectToLoginInterceptor {
573
+ constructor(router, loginPath) {
574
+ this.router = router;
575
+ this.loginPath = loginPath;
576
+ }
577
+ /**
578
+ * @override
579
+ */
580
+ intercept(req, next) {
581
+ return next.handle(req).pipe(catchError((err) => {
582
+ if (err instanceof HttpErrorResponse) {
583
+ if (err.status === 401) {
584
+ this.router.navigate([this.loginPath]);
585
+ }
586
+ }
587
+ return throwError(err);
588
+ }));
589
+ }
590
+ }
591
+ RedirectToLoginInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: RedirectToLoginInterceptor, deps: [{ token: i1.Router }, { token: DDR_LOGIN_PATH }], target: i0.ɵɵFactoryTarget.Injectable });
592
+ RedirectToLoginInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: RedirectToLoginInterceptor });
593
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: RedirectToLoginInterceptor, decorators: [{
594
+ type: Injectable
595
+ }], ctorParameters: function () {
596
+ return [{ type: i1.Router }, { type: undefined, decorators: [{
597
+ type: Inject,
598
+ args: [DDR_LOGIN_PATH]
599
+ }] }];
600
+ } });
601
+
602
+ class JwtService {
603
+ constructor(storagePrefix) {
604
+ this.storagePrefix = storagePrefix;
605
+ /**
606
+ * The current token.
607
+ */
608
+ this.token = null;
609
+ /**
610
+ * The expiry of the current token.
611
+ */
612
+ this.tokenExpiry = null;
613
+ }
614
+ /**
615
+ * Sets the current token and a refresh token.
616
+ */
617
+ setTokens(token, refreshToken) {
618
+ this.setToken(token);
619
+ localStorage.setItem(this.getRefreshTokenStorageKey(), refreshToken);
620
+ }
621
+ /**
622
+ * Sets the current token.
623
+ */
624
+ setToken(token) {
625
+ this.token = token;
626
+ const decodedToken = JSON.parse(atob(token.split('.')[1]));
627
+ this.tokenExpiry = decodedToken.exp * 1000;
628
+ console.log('New refresh token, expiry', new Date(this.tokenExpiry));
629
+ }
630
+ /**
631
+ * Gets the current token.
632
+ */
633
+ getToken() {
634
+ return this.token;
635
+ }
636
+ /**
637
+ * Gets the refresh token.
638
+ */
639
+ getRefreshToken() {
640
+ return localStorage.getItem(this.getRefreshTokenStorageKey());
641
+ }
642
+ /**
643
+ * Checks if the current token expired.
644
+ */
645
+ isExpired() {
646
+ const now = new Date().getTime();
647
+ return null == this.tokenExpiry || this.tokenExpiry < now;
648
+ }
649
+ /**
650
+ * Checks if the current token is about to expire.
651
+ * @param expiryMs
652
+ */
653
+ isAboutToExpire(expiryMs = 60000) {
654
+ const now = new Date().getTime();
655
+ return null == this.tokenExpiry || this.tokenExpiry - expiryMs < now;
656
+ }
657
+ /**
658
+ * Clears all token information.
659
+ */
660
+ clear() {
661
+ this.token = null;
662
+ this.tokenExpiry = null;
663
+ localStorage.removeItem(this.getRefreshTokenStorageKey());
664
+ }
665
+ getRefreshTokenStorageKey() {
666
+ return this.storagePrefix + '.jwt.refresh_token';
667
+ }
668
+ }
669
+ JwtService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: JwtService, deps: [{ token: DDR_STORAGE_PREFIX }], target: i0.ɵɵFactoryTarget.Injectable });
670
+ JwtService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: JwtService, providedIn: 'root' });
671
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: JwtService, decorators: [{
672
+ type: Injectable,
673
+ args: [{
674
+ providedIn: 'root'
675
+ }]
676
+ }], ctorParameters: function () {
677
+ return [{ type: undefined, decorators: [{
678
+ type: Inject,
679
+ args: [DDR_STORAGE_PREFIX]
680
+ }] }];
681
+ } });
682
+
683
+ class JwtInterceptor {
684
+ constructor(jwtService) {
685
+ this.jwtService = jwtService;
686
+ }
687
+ /**
688
+ * @override
689
+ */
690
+ intercept(req, next) {
691
+ const token = this.jwtService.getToken();
692
+ if (null !== token && !this.jwtService.isExpired()) {
693
+ req = req.clone({
694
+ headers: req.headers.set('Authorization', 'Bearer ' + token)
695
+ });
696
+ }
697
+ return next.handle(req);
698
+ }
699
+ }
700
+ JwtInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: JwtInterceptor, deps: [{ token: JwtService }], target: i0.ɵɵFactoryTarget.Injectable });
701
+ JwtInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: JwtInterceptor });
702
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: JwtInterceptor, decorators: [{
703
+ type: Injectable
704
+ }], ctorParameters: function () { return [{ type: JwtService }]; } });
705
+
706
+ class JwtRefreshTokenInterceptor {
707
+ constructor(jwtService, httpClient, jwtRefreshTokenUrl) {
708
+ this.jwtService = jwtService;
709
+ this.httpClient = httpClient;
710
+ this.jwtRefreshTokenUrl = jwtRefreshTokenUrl;
711
+ this.refreshTokenRequest$ = null;
712
+ }
713
+ /**
714
+ * @override
715
+ */
716
+ intercept(req, next) {
717
+ if (this.jwtService.isAboutToExpire() && !(req.url === this.jwtRefreshTokenUrl)) {
718
+ const refreshToken = this.jwtService.getRefreshToken();
719
+ if (null != refreshToken) {
720
+ return this.getRefreshTokenRequest(refreshToken).pipe(switchMap(() => next.handle(req)));
721
+ }
722
+ }
723
+ return next.handle(req);
724
+ }
725
+ getRefreshTokenRequest(refreshToken) {
726
+ if (null == this.refreshTokenRequest$) {
727
+ this.refreshTokenRequest$ = this.httpClient.post(this.jwtRefreshTokenUrl, { refresh_token: refreshToken }).pipe(map(response => {
728
+ this.jwtService.setTokens(response.token, response.refresh_token);
729
+ this.refreshTokenRequest$ = null;
730
+ return response;
731
+ }), catchError(error => {
732
+ this.jwtService.clear();
733
+ this.refreshTokenRequest$ = null;
734
+ return throwError(error);
735
+ }), shareReplay(1));
736
+ }
737
+ return this.refreshTokenRequest$;
738
+ }
739
+ }
740
+ JwtRefreshTokenInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: JwtRefreshTokenInterceptor, deps: [{ token: JwtService }, { token: i2$1.HttpClient }, { token: DDR_JWT_REFRESH_TOKEN_URL }], target: i0.ɵɵFactoryTarget.Injectable });
741
+ JwtRefreshTokenInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: JwtRefreshTokenInterceptor });
742
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: JwtRefreshTokenInterceptor, decorators: [{
743
+ type: Injectable
744
+ }], ctorParameters: function () {
745
+ return [{ type: JwtService }, { type: i2$1.HttpClient }, { type: undefined, decorators: [{
746
+ type: Inject,
747
+ args: [DDR_JWT_REFRESH_TOKEN_URL]
748
+ }] }];
749
+ } });
750
+
751
+ /*
752
+ * Public API Surface of ngx-extensions
753
+ */
754
+
755
+ /**
756
+ * Generated bundle index. Do not edit.
757
+ */
758
+
759
+ export { BottomHitDirective, CollectionUtils, CookieService, DDR_JWT_REFRESH_TOKEN_URL, DDR_LOGIN_PATH, DDR_STORAGE_PREFIX, DdrExtensionsModule, Debounce, JwtInterceptor, JwtRefreshTokenInterceptor, JwtService, LazyImageDirective, Limit, NumberUtils, ObjectUtils, RedirectToLoginInterceptor, ScrollService, StringUtils, TypeUtils, UrlInfo, VisibilityService, WithCredentialsInterceptor };
760
+ //# sourceMappingURL=dontdrinkandroot-ngx-extensions.mjs.map