http-request-manager 15.0.19 → 15.0.26

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 (224) hide show
  1. package/ng-package.json +8 -0
  2. package/package.json +10 -14
  3. package/src/lib/http-request-manager.module.ts +101 -0
  4. package/src/lib/http-request-services-demo/database-data-demo/database-data-demo.component.html +3 -0
  5. package/src/lib/http-request-services-demo/database-data-demo/database-data-demo.component.scss +0 -0
  6. package/src/lib/http-request-services-demo/database-data-demo/database-data-demo.component.ts +105 -0
  7. package/src/lib/http-request-services-demo/http-request-services-demo.component.html +64 -0
  8. package/src/lib/http-request-services-demo/http-request-services-demo.component.scss +6 -0
  9. package/src/lib/http-request-services-demo/http-request-services-demo.component.ts +34 -0
  10. package/src/lib/http-request-services-demo/local-storage-demo/local-storage-demo.component.html +195 -0
  11. package/src/lib/http-request-services-demo/local-storage-demo/local-storage-demo.component.scss +17 -0
  12. package/src/lib/http-request-services-demo/local-storage-demo/local-storage-demo.component.ts +205 -0
  13. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/download-file/download-file.component.html +59 -0
  14. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/download-file/download-file.component.scss +60 -0
  15. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/download-file/download-file.component.ts +71 -0
  16. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/file-download.module.ts +28 -0
  17. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/file-downloader.component.html +10 -0
  18. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/file-downloader.component.scss +29 -0
  19. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/file-downloader.component.ts +99 -0
  20. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/models/download-labels-model.ts +22 -0
  21. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/spinner/spinner.component.html +8 -0
  22. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/spinner/spinner.component.scss +19 -0
  23. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/spinner/spinner.component.ts +25 -0
  24. package/src/lib/http-request-services-demo/request-manager-demo/models/app-session.model.ts +30 -0
  25. package/src/lib/http-request-services-demo/request-manager-demo/models/app.model.ts +19 -0
  26. package/src/lib/http-request-services-demo/request-manager-demo/models/get-sample.model.ts +25 -0
  27. package/src/lib/http-request-services-demo/request-manager-demo/models/sample-ai-prompt.ts +19 -0
  28. package/src/lib/http-request-services-demo/request-manager-demo/models/sample-client-details.ts +24 -0
  29. package/src/lib/http-request-services-demo/request-manager-demo/models/sample-client-info.ts +30 -0
  30. package/src/lib/http-request-services-demo/request-manager-demo/models/sample-client.model.ts +49 -0
  31. package/src/lib/http-request-services-demo/request-manager-demo/models/sample-mapper-client-info.ts +33 -0
  32. package/src/lib/http-request-services-demo/request-manager-demo/request-manager-demo.component.html +336 -0
  33. package/src/lib/http-request-services-demo/request-manager-demo/request-manager-demo.component.scss +24 -0
  34. package/src/lib/http-request-services-demo/request-manager-demo/request-manager-demo.component.ts +403 -0
  35. package/src/lib/http-request-services-demo/request-manager-state-demo/request-manager-state-demo.component.html +328 -0
  36. package/src/lib/http-request-services-demo/request-manager-state-demo/request-manager-state-demo.component.scss +24 -0
  37. package/src/lib/http-request-services-demo/request-manager-state-demo/request-manager-state-demo.component.ts +347 -0
  38. package/src/lib/http-request-services-demo/request-manager-state-demo/services/state-manager-demo.service.ts +88 -0
  39. package/src/lib/index.ts +3 -0
  40. package/src/lib/interceptors/credentials.interceptor.ts +18 -0
  41. package/{lib/interceptors/index.d.ts → src/lib/interceptors/index.ts} +2 -0
  42. package/src/lib/interceptors/models/error-settings.model.ts +22 -0
  43. package/src/lib/interceptors/proxy-debugger.interceptor.ts +46 -0
  44. package/src/lib/interceptors/request-error.interceptor.ts +65 -0
  45. package/src/lib/interceptors/request-header.interceptor.ts +58 -0
  46. package/src/lib/models/config-http-options.model.ts +42 -0
  47. package/src/lib/models/config-local-storage-options.model.ts +27 -0
  48. package/src/lib/models/config-options.model.ts +27 -0
  49. package/{lib/models/config-token.model.d.ts → src/lib/models/config-token.model.ts} +2 -1
  50. package/src/lib/models/data-type.enum.ts +5 -0
  51. package/src/lib/models/database-storage.model.ts +24 -0
  52. package/src/lib/models/index.ts +9 -0
  53. package/src/lib/models/retry-options.model.ts +22 -0
  54. package/src/lib/services/database-manager-services/database.manager.service.ts +193 -0
  55. package/src/lib/services/database-manager-services/db.storage.service.ts +191 -0
  56. package/src/lib/services/database-manager-services/index.ts +4 -0
  57. package/src/lib/services/database-manager-services/models/table-schema.ts +35 -0
  58. package/{lib/services/index.d.ts → src/lib/services/index.ts} +4 -0
  59. package/src/lib/services/local-storage-manager-service/index.ts +2 -0
  60. package/src/lib/services/local-storage-manager-service/local-storage-manager.service.spec.ts +71 -0
  61. package/src/lib/services/local-storage-manager-service/local-storage-manager.service.ts +421 -0
  62. package/src/lib/services/local-storage-manager-service/models/global-store-options.model.ts +30 -0
  63. package/{lib/services/local-storage-manager-service/models/index.d.ts → src/lib/services/local-storage-manager-service/models/index.ts} +2 -1
  64. package/src/lib/services/local-storage-manager-service/models/setting-options.model.ts +30 -0
  65. package/src/lib/services/local-storage-manager-service/models/storage-data.model.ts +24 -0
  66. package/src/lib/services/local-storage-manager-service/models/storage-option.model.ts +29 -0
  67. package/src/lib/services/local-storage-manager-service/models/storage-type.enum.ts +5 -0
  68. package/src/lib/services/request-manager-services/README.md +268 -0
  69. package/src/lib/services/request-manager-services/http-manager.service.spec.ts +230 -0
  70. package/src/lib/services/request-manager-services/http-manager.service.ts +274 -0
  71. package/{lib/services/request-manager-services/index.d.ts → src/lib/services/request-manager-services/index.ts} +2 -0
  72. package/src/lib/services/request-manager-services/request.service.ts +261 -0
  73. package/src/lib/services/request-manager-services/rxjs-operators/countdown.ts +17 -0
  74. package/src/lib/services/request-manager-services/rxjs-operators/delay-retry.ts +16 -0
  75. package/src/lib/services/request-manager-services/rxjs-operators/request-polling.ts +21 -0
  76. package/src/lib/services/request-manager-services/rxjs-operators/request-streaming.ts +32 -0
  77. package/src/lib/services/request-manager-state-service/http-manager-state.store.ts +402 -0
  78. package/{lib/services/request-manager-state-service/index.d.ts → src/lib/services/request-manager-state-service/index.ts} +1 -0
  79. package/src/lib/services/request-manager-state-service/models/api-request.model.ts +50 -0
  80. package/{lib/services/request-manager-state-service/models/index.d.ts → src/lib/services/request-manager-state-service/models/index.ts} +1 -0
  81. package/src/lib/services/request-manager-state-service/models/request-options.model.ts +22 -0
  82. package/src/lib/services/utils/app.service.spec.ts +25 -0
  83. package/src/lib/services/utils/app.service.ts +21 -0
  84. package/src/lib/services/utils/encryption/README.md +79 -0
  85. package/src/lib/services/utils/encryption/asymmetrical-encryption.service.ts +282 -0
  86. package/src/lib/services/utils/encryption/encryption-test.service.ts +39 -0
  87. package/{lib/services/utils/encryption/index.d.ts → src/lib/services/utils/encryption/index.ts} +2 -0
  88. package/src/lib/services/utils/encryption/random.ts +69 -0
  89. package/src/lib/services/utils/encryption/symmetrical-encryption.service.ts +93 -0
  90. package/src/lib/services/utils/headers.service.spec.ts +80 -0
  91. package/src/lib/services/utils/headers.service.ts +18 -0
  92. package/{lib/services/utils/index.d.ts → src/lib/services/utils/index.ts} +2 -0
  93. package/src/lib/services/utils/object-merger.service.spec.ts +16 -0
  94. package/src/lib/services/utils/object-merger.service.ts +60 -0
  95. package/src/lib/services/utils/path-query.service.spec.ts +117 -0
  96. package/src/lib/services/utils/path-query.service.ts +69 -0
  97. package/src/lib/services/utils/utils.service.spec.ts +164 -0
  98. package/src/lib/services/utils/utils.service.ts +192 -0
  99. package/src/public-api.ts +14 -0
  100. package/tsconfig.lib.json +32 -0
  101. package/tsconfig.lib.prod.json +10 -0
  102. package/tsconfig.spec.json +14 -0
  103. package/esm2022/http-request-manager.mjs +0 -5
  104. package/esm2022/lib/http-request-manager.module.mjs +0 -146
  105. package/esm2022/lib/http-request-services-demo/http-request-services-demo.component.mjs +0 -41
  106. package/esm2022/lib/http-request-services-demo/local-storage-demo/local-storage-demo.component.mjs +0 -173
  107. package/esm2022/lib/http-request-services-demo/request-manager-demo/file-downloader/download-file/download-file.component.mjs +0 -80
  108. package/esm2022/lib/http-request-services-demo/request-manager-demo/file-downloader/file-download.module.mjs +0 -42
  109. package/esm2022/lib/http-request-services-demo/request-manager-demo/file-downloader/file-downloader.component.mjs +0 -88
  110. package/esm2022/lib/http-request-services-demo/request-manager-demo/file-downloader/models/download-labels-model.mjs +0 -11
  111. package/esm2022/lib/http-request-services-demo/request-manager-demo/file-downloader/spinner/spinner.component.mjs +0 -29
  112. package/esm2022/lib/http-request-services-demo/request-manager-demo/models/sample-ai-prompt.mjs +0 -9
  113. package/esm2022/lib/http-request-services-demo/request-manager-demo/models/sample-client-info.mjs +0 -12
  114. package/esm2022/lib/http-request-services-demo/request-manager-demo/models/sample-mapper-client-info.mjs +0 -14
  115. package/esm2022/lib/http-request-services-demo/request-manager-demo/request-manager-demo.component.mjs +0 -315
  116. package/esm2022/lib/http-request-services-demo/request-manager-state-demo/request-manager-state-demo.component.mjs +0 -270
  117. package/esm2022/lib/http-request-services-demo/request-manager-state-demo/services/state-manager-demo.service.mjs +0 -67
  118. package/esm2022/lib/index.mjs +0 -4
  119. package/esm2022/lib/interceptors/credentials.interceptor.mjs +0 -14
  120. package/esm2022/lib/interceptors/index.mjs +0 -5
  121. package/esm2022/lib/interceptors/models/error-settings.model.mjs +0 -10
  122. package/esm2022/lib/interceptors/proxy-debugger.interceptor.mjs +0 -47
  123. package/esm2022/lib/interceptors/request-error.interceptor.mjs +0 -49
  124. package/esm2022/lib/interceptors/request-header.interceptor.mjs +0 -41
  125. package/esm2022/lib/models/config-http-options.model.mjs +0 -18
  126. package/esm2022/lib/models/config-local-storage-options.model.mjs +0 -12
  127. package/esm2022/lib/models/config-options.model.mjs +0 -12
  128. package/esm2022/lib/models/config-token.model.mjs +0 -8
  129. package/esm2022/lib/models/data-type.enum.mjs +0 -7
  130. package/esm2022/lib/models/database-storage.model.mjs +0 -10
  131. package/esm2022/lib/models/index.mjs +0 -7
  132. package/esm2022/lib/models/retry-options.model.mjs +0 -10
  133. package/esm2022/lib/services/index.mjs +0 -6
  134. package/esm2022/lib/services/local-storage-manager-service/index.mjs +0 -3
  135. package/esm2022/lib/services/local-storage-manager-service/local-storage-manager.service.mjs +0 -302
  136. package/esm2022/lib/services/local-storage-manager-service/models/global-store-options.model.mjs +0 -13
  137. package/esm2022/lib/services/local-storage-manager-service/models/index.mjs +0 -6
  138. package/esm2022/lib/services/local-storage-manager-service/models/setting-options.model.mjs +0 -13
  139. package/esm2022/lib/services/local-storage-manager-service/models/storage-data.model.mjs +0 -10
  140. package/esm2022/lib/services/local-storage-manager-service/models/storage-option.model.mjs +0 -12
  141. package/esm2022/lib/services/local-storage-manager-service/models/storage-type.enum.mjs +0 -7
  142. package/esm2022/lib/services/request-manager-services/http-manager.service.mjs +0 -207
  143. package/esm2022/lib/services/request-manager-services/index.mjs +0 -5
  144. package/esm2022/lib/services/request-manager-services/request.service.mjs +0 -189
  145. package/esm2022/lib/services/request-manager-services/rxjs-operators/countdown.mjs +0 -9
  146. package/esm2022/lib/services/request-manager-services/rxjs-operators/delay-retry.mjs +0 -10
  147. package/esm2022/lib/services/request-manager-services/rxjs-operators/index.mjs +0 -5
  148. package/esm2022/lib/services/request-manager-services/rxjs-operators/request-polling.mjs +0 -14
  149. package/esm2022/lib/services/request-manager-services/rxjs-operators/request-streaming.mjs +0 -19
  150. package/esm2022/lib/services/request-manager-state-service/http-manager-state.store.mjs +0 -267
  151. package/esm2022/lib/services/request-manager-state-service/index.mjs +0 -3
  152. package/esm2022/lib/services/request-manager-state-service/models/api-request.model.mjs +0 -20
  153. package/esm2022/lib/services/request-manager-state-service/models/index.mjs +0 -3
  154. package/esm2022/lib/services/request-manager-state-service/models/request-options.model.mjs +0 -10
  155. package/esm2022/lib/services/utils/app.service.mjs +0 -26
  156. package/esm2022/lib/services/utils/encryption/asymmetrical-encryption.service.mjs +0 -186
  157. package/esm2022/lib/services/utils/encryption/encryption-test.service.mjs +0 -35
  158. package/esm2022/lib/services/utils/encryption/index.mjs +0 -4
  159. package/esm2022/lib/services/utils/encryption/random.mjs +0 -52
  160. package/esm2022/lib/services/utils/encryption/symmetrical-encryption.service.mjs +0 -77
  161. package/esm2022/lib/services/utils/headers.service.mjs +0 -21
  162. package/esm2022/lib/services/utils/index.mjs +0 -6
  163. package/esm2022/lib/services/utils/object-merger.service.mjs +0 -50
  164. package/esm2022/lib/services/utils/path-query.service.mjs +0 -54
  165. package/esm2022/lib/services/utils/utils.service.mjs +0 -155
  166. package/esm2022/public-api.mjs +0 -7
  167. package/fesm2022/http-request-manager.mjs +0 -3102
  168. package/fesm2022/http-request-manager.mjs.map +0 -1
  169. package/http-request-manager-15.0.19.tgz +0 -0
  170. package/index.d.ts +0 -5
  171. package/lib/http-request-manager.module.d.ts +0 -33
  172. package/lib/http-request-services-demo/http-request-services-demo.component.d.ts +0 -24
  173. package/lib/http-request-services-demo/local-storage-demo/local-storage-demo.component.d.ts +0 -56
  174. package/lib/http-request-services-demo/request-manager-demo/file-downloader/download-file/download-file.component.d.ts +0 -26
  175. package/lib/http-request-services-demo/request-manager-demo/file-downloader/file-download.module.d.ts +0 -13
  176. package/lib/http-request-services-demo/request-manager-demo/file-downloader/file-downloader.component.d.ts +0 -27
  177. package/lib/http-request-services-demo/request-manager-demo/file-downloader/models/download-labels-model.d.ts +0 -12
  178. package/lib/http-request-services-demo/request-manager-demo/file-downloader/spinner/spinner.component.d.ts +0 -16
  179. package/lib/http-request-services-demo/request-manager-demo/models/sample-ai-prompt.d.ts +0 -8
  180. package/lib/http-request-services-demo/request-manager-demo/models/sample-client-info.d.ts +0 -14
  181. package/lib/http-request-services-demo/request-manager-demo/models/sample-mapper-client-info.d.ts +0 -14
  182. package/lib/http-request-services-demo/request-manager-demo/request-manager-demo.component.d.ts +0 -107
  183. package/lib/http-request-services-demo/request-manager-state-demo/request-manager-state-demo.component.d.ts +0 -122
  184. package/lib/http-request-services-demo/request-manager-state-demo/services/state-manager-demo.service.d.ts +0 -15
  185. package/lib/index.d.ts +0 -3
  186. package/lib/interceptors/credentials.interceptor.d.ts +0 -8
  187. package/lib/interceptors/models/error-settings.model.d.ts +0 -10
  188. package/lib/interceptors/proxy-debugger.interceptor.d.ts +0 -12
  189. package/lib/interceptors/request-error.interceptor.d.ts +0 -10
  190. package/lib/interceptors/request-header.interceptor.d.ts +0 -15
  191. package/lib/models/config-http-options.model.d.ts +0 -21
  192. package/lib/models/config-local-storage-options.model.d.ts +0 -13
  193. package/lib/models/config-options.model.d.ts +0 -12
  194. package/lib/models/data-type.enum.d.ts +0 -5
  195. package/lib/models/database-storage.model.d.ts +0 -10
  196. package/lib/models/index.d.ts +0 -6
  197. package/lib/models/retry-options.model.d.ts +0 -10
  198. package/lib/services/local-storage-manager-service/index.d.ts +0 -2
  199. package/lib/services/local-storage-manager-service/local-storage-manager.service.d.ts +0 -86
  200. package/lib/services/local-storage-manager-service/models/global-store-options.model.d.ts +0 -15
  201. package/lib/services/local-storage-manager-service/models/setting-options.model.d.ts +0 -15
  202. package/lib/services/local-storage-manager-service/models/storage-data.model.d.ts +0 -10
  203. package/lib/services/local-storage-manager-service/models/storage-option.model.d.ts +0 -13
  204. package/lib/services/local-storage-manager-service/models/storage-type.enum.d.ts +0 -5
  205. package/lib/services/request-manager-services/http-manager.service.d.ts +0 -41
  206. package/lib/services/request-manager-services/request.service.d.ts +0 -27
  207. package/lib/services/request-manager-services/rxjs-operators/countdown.d.ts +0 -2
  208. package/lib/services/request-manager-services/rxjs-operators/delay-retry.d.ts +0 -2
  209. package/lib/services/request-manager-services/rxjs-operators/request-polling.d.ts +0 -7
  210. package/lib/services/request-manager-services/rxjs-operators/request-streaming.d.ts +0 -2
  211. package/lib/services/request-manager-state-service/http-manager-state.store.d.ts +0 -51
  212. package/lib/services/request-manager-state-service/models/api-request.model.d.ts +0 -27
  213. package/lib/services/request-manager-state-service/models/request-options.model.d.ts +0 -10
  214. package/lib/services/utils/app.service.d.ts +0 -8
  215. package/lib/services/utils/encryption/asymmetrical-encryption.service.d.ts +0 -17
  216. package/lib/services/utils/encryption/encryption-test.service.d.ts +0 -10
  217. package/lib/services/utils/encryption/random.d.ts +0 -7
  218. package/lib/services/utils/encryption/symmetrical-encryption.service.d.ts +0 -14
  219. package/lib/services/utils/headers.service.d.ts +0 -10
  220. package/lib/services/utils/object-merger.service.d.ts +0 -12
  221. package/lib/services/utils/path-query.service.d.ts +0 -11
  222. package/lib/services/utils/utils.service.d.ts +0 -24
  223. package/public-api.d.ts +0 -3
  224. /package/{lib/services/request-manager-services/rxjs-operators/index.d.ts → src/lib/services/request-manager-services/rxjs-operators/index.ts} +0 -0
@@ -0,0 +1,274 @@
1
+ import { Inject, inject, Injectable, Injector, Optional } from '@angular/core';
2
+ import { HttpErrorResponse } from '@angular/common/http';
3
+ import { BehaviorSubject, Observable, Subject, throwError } from 'rxjs';
4
+ import { tap, map, finalize, catchError } from 'rxjs/operators';
5
+
6
+ import { ApiRequest } from '../request-manager-state-service/models/api-request.model';
7
+ import { RequestService } from './request.service';
8
+ import { requestPolling, countdown, delayedRetry } from './rxjs-operators';
9
+
10
+ import { ToastColors, ToastDisplay, ToastMessageDisplayService } from 'toast-message-display';
11
+
12
+ import { CONFIG_SETTINGS_TOKEN } from '../../models/config-token.model';
13
+ import { ConfigOptions } from '../../models';
14
+ import { ObjectMergerService } from '../utils/object-merger.service';
15
+
16
+ @Injectable({
17
+ providedIn: 'root',
18
+ })
19
+ export class HTTPManagerService<T> extends RequestService {
20
+
21
+ toastMessage = inject(ToastMessageDisplayService)
22
+ ng_injector = inject(Injector)
23
+ objectMergerService = inject(ObjectMergerService)
24
+
25
+ private countdown = new BehaviorSubject<number>(0);
26
+ countdown$ = this.countdown.asObservable();
27
+
28
+ private error = new BehaviorSubject<boolean>(false);
29
+ error$ = this.error.asObservable();
30
+
31
+ private data = new BehaviorSubject<any>(null)
32
+ data$ = this.data.asObservable()
33
+
34
+ private polling$ = new Subject<void>();
35
+
36
+ config = ApiRequest.adapt();
37
+
38
+ constructor(@Optional() @Inject(CONFIG_SETTINGS_TOKEN) private configOptions?: ConfigOptions) {
39
+ super()
40
+ this.config = (configOptions) ? ApiRequest.adapt(configOptions.httpRequestOptions) : this.config
41
+ }
42
+
43
+ // REQUESTS
44
+
45
+ getRequest<T>(options?: ApiRequest, params?: any[]) {
46
+
47
+ this.isPending.next(true);
48
+ this.data.next(null)
49
+
50
+ const updatedOptions = this.defineReqOptions(options, params)
51
+ const func = this.getRecordRequest;
52
+ const requests = this.createRequest(func, updatedOptions);
53
+
54
+ return this.createObservable<T>(updatedOptions, requests, func.name)
55
+ .pipe(
56
+ tap(data => this.data.next(data))
57
+ ).pipe(
58
+ finalize(() => this.isPending.next(false)),
59
+ catchError((err) => {
60
+ if(updatedOptions.displayError) this.handleErrorWithSnackBar(err)
61
+ this.isPending.next(false)
62
+ return this.handleError(err);
63
+ })
64
+ )
65
+ }
66
+
67
+ postRequest<T extends { id?: number|string }>(data: T, options: ApiRequest, params?: any[]) {
68
+
69
+ this.isPending.next(true);
70
+ this.data.next(null)
71
+
72
+ const updatedOptions = this.defineReqOptions(options, params)
73
+ const func = this.createRecordRequest;
74
+ const requests = this.createRequest(func, updatedOptions, data);
75
+
76
+ return this.createObservable<T>(updatedOptions, requests, func.name).pipe(tap(data => this.data.next(data)))
77
+ .pipe(
78
+ finalize(() => this.isPending.next(false)),
79
+ catchError((err) => {
80
+ if(updatedOptions.displayError) this.handleErrorWithSnackBar(err)
81
+ this.isPending.next(false)
82
+ return this.handleError(err);
83
+ })
84
+ )
85
+ }
86
+
87
+ putRequest<T extends { id?: number|string }>(data: T, options: ApiRequest, params?: any[]) {
88
+
89
+ this.isPending.next(true);
90
+ this.data.next(null)
91
+
92
+ const updatedOptions = this.defineReqOptions(options, params)
93
+ const func = this.updateRecordRequest;
94
+ const requests = this.createRequest(func, updatedOptions, data);
95
+
96
+ return this.createObservable<T>(updatedOptions, requests, func.name).pipe(tap(data => this.data.next(data)))
97
+ .pipe(
98
+ finalize(() => this.isPending.next(false)),
99
+ catchError((err) => {
100
+ if(updatedOptions.displayError) this.handleErrorWithSnackBar(err)
101
+ this.isPending.next(false)
102
+ return this.handleError(err);
103
+ })
104
+ )
105
+ }
106
+
107
+ deleteRequest<T>(options: ApiRequest, params?: any[]) {
108
+
109
+ this.isPending.next(true);
110
+ this.data.next(null)
111
+
112
+ const updatedOptions = this.defineReqOptions(options, params)
113
+ const func = this.deleteRecordRequest;
114
+ const requests = this.createRequest(func, updatedOptions);
115
+
116
+ return this.createObservable<T>(updatedOptions, requests, func.name).pipe(tap(data => this.data.next(data)))
117
+ .pipe(
118
+ finalize(() => this.isPending.next(false)),
119
+ catchError((err) => {
120
+ if(updatedOptions.displayError) this.handleErrorWithSnackBar(err)
121
+ this.isPending.next(false)
122
+ return this.handleError(err);
123
+ })
124
+ )
125
+ }
126
+
127
+ downloadRequest<T>(options: ApiRequest, params?: any[], saveAs?: string) {
128
+
129
+ this.isPending.next(true);
130
+
131
+ const updatedOptions = this.defineReqOptions(options, params)
132
+ const func = this.downloadFileRequest;
133
+ const requests = this.createRequest(func, updatedOptions)
134
+
135
+ return this.createObservable<T>(updatedOptions, requests, func.name)
136
+ .pipe(
137
+ catchError((err) => {
138
+ this.error.next(true)
139
+ this.isPending.next(false)
140
+ return this.handleError(err);
141
+ })
142
+ )
143
+
144
+ }
145
+
146
+ private createObservable<T>(options: ApiRequest, request$: Observable<T>, funcName: string) {
147
+
148
+ const polling = options.polling ? (options.polling > 0 ? true : false) : false;
149
+ const isPolling =
150
+ polling &&
151
+ !(funcName === 'deleteRecordRequest' || funcName === 'updateRecordRequest' || funcName === 'createRecordRequest')
152
+ ? true
153
+ : false;
154
+
155
+ this.polling$.next();
156
+
157
+ const polling$ =
158
+ (isPolling && options.polling) || 0 >= 3
159
+ ? request$.pipe(
160
+ requestPolling((options.polling || 0) + 1, this.polling$, this.isPending),
161
+ tap(() => this.countdown.next(0)),
162
+ tap(() => {
163
+ if (!options.polling) return;
164
+ const count = options.polling ? options.polling : 0;
165
+ // console.log('COUNT:', count);
166
+ countdown(count)
167
+ .pipe(
168
+ map((x: number) => {
169
+ // console.log('XX:', count, x);
170
+ const pollingInSec = options.polling || 0;
171
+ const percentageCompleted = ((pollingInSec - x) / pollingInSec) * 100;
172
+ return Math.round(percentageCompleted);
173
+ })
174
+ )
175
+ .subscribe((countDownValue: number) => {
176
+ // console.log(this.countdown.value, countDownValue);
177
+ this.countdown.next(countDownValue);
178
+ });
179
+ }),
180
+ )
181
+ : request$.pipe(
182
+ catchError((err: any) => {
183
+
184
+ if (err instanceof HttpErrorResponse) {
185
+ this.error.next(true);
186
+ return this.handleError(err);
187
+ }
188
+
189
+ return throwError(() => err);
190
+ }),
191
+ // finalize(() => this.isPending.next(false))
192
+ )
193
+
194
+ return polling$.pipe(
195
+ catchError((err: any, caught: Observable<T>) => {
196
+
197
+ if (err instanceof HttpErrorResponse) {
198
+ this.error.next(true);
199
+ if(isPolling) this.stopPolling();
200
+ return this.handleError(err);
201
+ }
202
+
203
+ return throwError(() => err);
204
+ }),
205
+ (options?.retry && options.retry.times > 0)
206
+ ? delayedRetry((options.retry.delay || 3) * 1000, (options.retry.times || 0) - 1)
207
+ : (source: Observable<T>) => source
208
+ );
209
+ }
210
+
211
+ private createRequest(func: Function, options: ApiRequest, data?: any | any[]) {
212
+ const dataItem = this.prepareRequestData(options, data, func.name);
213
+ return func.bind(this)(dataItem.options, dataItem.data);
214
+ }
215
+
216
+ private prepareRequestData(options: ApiRequest, data: any, funcName: string) {
217
+
218
+ if ((options.mapper && funcName === 'updateRecordRequest') || funcName === 'createRecordRequest') {
219
+ if (options?.mapper) {
220
+ data = options.mapper
221
+ ? Array.isArray(data)
222
+ ? map((item) => options.mapper(item))
223
+ : options.mapper(data)
224
+ : data;
225
+ }
226
+ } else {
227
+ if (options?.adapter) {
228
+ data = Array.isArray(data)
229
+ ? map((item) => options.adapter(item))
230
+ : options.adapter(data)
231
+ }
232
+ }
233
+
234
+ return { options: options, data: data };
235
+ }
236
+
237
+ // MISC
238
+
239
+ private handleError(error: Response | any) {
240
+ this.error.next(error.message || `${error.status} - ${error.statusText}`)
241
+ return throwError(() => error)
242
+ }
243
+
244
+ private handleErrorWithSnackBar(error: Response | any) {
245
+
246
+ const displayError = ToastDisplay.adapt({
247
+ message: error.message || `${error.status} - ${error.statusText}`,
248
+ action: 'OK',
249
+ color: ToastColors.ERROR,
250
+ icon: 'error',
251
+ duration: 5 * 1000, //5 seconds
252
+ })
253
+
254
+ this.toastMessage.toastMessage(displayError)
255
+
256
+ }
257
+
258
+ private stopPolling() {
259
+ this.isPending.next(false);
260
+ this.polling$.next();
261
+ }
262
+
263
+ private defineReqOptions(options: any, params?: any[]) {
264
+
265
+ const req = ApiRequest.adapt(options)
266
+ if(req?.path) req.path = (params) ? [...req.path, ...params] : req.path
267
+
268
+ const optionsReq = (req)? req : ApiRequest.adapt()
269
+ const updatedOptions = this.objectMergerService.mergeOptions(optionsReq)
270
+
271
+ return updatedOptions
272
+
273
+ }
274
+ }
@@ -1,3 +1,5 @@
1
1
  export * from "./http-manager.service";
2
+ // export * from './request.service';
3
+
2
4
  export * from "../../models/index";
3
5
  export * from "./rxjs-operators/index";
@@ -0,0 +1,261 @@
1
+ import { HttpClient, HttpEvent, HttpEventType, HttpHeaderResponse } from '@angular/common/http';
2
+ import { Injectable, inject } from '@angular/core';
3
+ import { BehaviorSubject, Observable, throwError } from 'rxjs';
4
+ import { catchError, delay, finalize, map } from 'rxjs/operators';
5
+
6
+ import { ApiRequest } from '../request-manager-state-service/models/api-request.model';
7
+ import { PathQueryService, HeadersService } from '../utils';
8
+ import { requestStreaming } from './rxjs-operators/request-streaming';
9
+
10
+
11
+ @Injectable({
12
+ providedIn: 'root'
13
+ })
14
+ export class RequestService {
15
+
16
+ private http = inject(HttpClient)
17
+
18
+ private pathQueryService = inject(PathQueryService)
19
+ private headersService = inject(HeadersService)
20
+
21
+ isPending = new BehaviorSubject<boolean>(false)
22
+ isPending$ = this.isPending.asObservable().pipe(delay(1))
23
+
24
+ progress = new BehaviorSubject<number>(0)
25
+ progress$ = this.progress.asObservable()
26
+
27
+ getRecordRequest<T>(options: ApiRequest): Observable<T> {
28
+
29
+ const urlPath = this.buildUrlPath(options);
30
+ const headers = this.buildCombinedHeaders(options);
31
+
32
+ this.isPending.next(true);
33
+
34
+ return (options.stream)
35
+ ? this.http.get<any>(urlPath, headers).pipe(
36
+ requestStreaming(),
37
+ this.handleFinalize()
38
+ )
39
+ : this.http.get<T>(urlPath, headers).pipe(
40
+ this.request(options),
41
+ )
42
+ }
43
+
44
+ createRecordRequest<T>(options: ApiRequest, data: any): Observable<T> {
45
+
46
+ const urlPath = this.buildUrlPath(options);
47
+ const headers = this.buildCombinedHeaders(options);
48
+
49
+ this.isPending.next(true);
50
+
51
+ return (options.stream)
52
+ ? this.http.post<any>(urlPath, data, headers).pipe(
53
+ requestStreaming(),
54
+ this.handleFinalize()
55
+ )
56
+ : this.http.post<T>(urlPath, data, headers).pipe(
57
+ this.request(options),
58
+ )
59
+ }
60
+
61
+ updateRecordRequest<T>(options: ApiRequest, data: any): Observable<T> {
62
+ const urlPath = this.buildUrlPath(options);
63
+ const headers = this.buildHeaders(options);
64
+
65
+ this.isPending.next(true);
66
+
67
+ return this.http.put<any>(urlPath, data, headers).pipe(
68
+ this.request(options),
69
+ )
70
+ }
71
+
72
+ deleteRecordRequest<T>(options: ApiRequest): Observable<T> {
73
+
74
+ const urlPath = this.buildUrlPath(options);
75
+ const headers = this.buildHeaders(options);
76
+
77
+ this.isPending.next(true);
78
+
79
+ return this.http.delete<any>(urlPath, headers).pipe(
80
+ this.request(options),
81
+ )
82
+ }
83
+
84
+ // Helper functions
85
+ private buildUrlPath(options: ApiRequest): string {
86
+ return this.pathQueryService.buildAPIPath(options.server, options.path);
87
+ }
88
+
89
+ private buildHeaders(options: ApiRequest): any {
90
+ return this.headersService.generateHeaders(options.headers);
91
+ }
92
+
93
+ private buildCombinedHeaders(options: ApiRequest): any {
94
+ const headers = this.headersService.generateHeaders(options.headers)
95
+ return this.combineHeaders(headers, options.stream || false)
96
+ }
97
+
98
+ private request<T>(options: ApiRequest): (source: Observable<any>) => Observable<T> {
99
+ return (source$: Observable<any>): Observable<T> => {
100
+ return source$.pipe(
101
+ map(data => {
102
+ if (options?.adapter) {
103
+ return Array.isArray(data)
104
+ ? data.map((item: any) => options.adapter(item))
105
+ : options.adapter(data)
106
+ }
107
+ return data
108
+ })
109
+ )
110
+ }
111
+ }
112
+
113
+ downloadFileRequest(options: ApiRequest): Observable<any> {
114
+
115
+ this.isPending.next(true);
116
+
117
+ const urlPath = this.buildUrlPath(options);
118
+
119
+ return this.http.get(urlPath, { responseType: 'blob', observe: 'events', reportProgress: true })
120
+ .pipe(
121
+ map((event: HttpEvent<any>) => {
122
+
123
+ this.isPending.next(true)
124
+
125
+ if (event instanceof HttpHeaderResponse) {
126
+ if(event.status !== 200) {
127
+ this.isPending.next(false)
128
+ throw new Error('Download failed');
129
+ }
130
+ }
131
+
132
+ // 0 Sent Request has been sent.
133
+ // 1 UploadProgress Upload is in progress.
134
+ // 2 ResponseHeader Response headers received.
135
+ // 3 DownloadProgress Download is in progress.
136
+ // 4 Response Response is fully received.
137
+ // 5 User Custom user event.
138
+
139
+ switch (event.type) {
140
+
141
+ case HttpEventType.DownloadProgress:
142
+
143
+ const status = (event.total) ? Math.round(event.loaded / (event.total || 1) * 100) : 100
144
+ this.progress.next(status)
145
+ return status
146
+
147
+ case HttpEventType.Response:
148
+
149
+ try {
150
+
151
+ const fileNamePath = (options?.saveAs) ? options.saveAs : (options.path) ? options.path[options.path.length - 1] : []
152
+ const header_content = event.headers.get('Content-Disposition') || '';
153
+ // checks if header_content is not empty and splits the header_content to get the file name
154
+ // otherwise, it will use the fileDownload - contains the file name and extension
155
+ const file = (header_content) ? header_content.split('=')[1].substring(0, header_content.split('=')[1].length) : ''
156
+
157
+ const fileName = (fileNamePath !== '') ? fileNamePath : file
158
+
159
+ if (fileName === '') {
160
+ this.isPending.next(false);
161
+ throw new Error('Save File: (file name and extension) not found in Headers or Path');
162
+ }
163
+
164
+ this.downloadFile(fileName, event.body)
165
+ this.isPending.next(false)
166
+
167
+ return 100
168
+
169
+ } catch (error) {
170
+ throw new Error('Download failed');
171
+ }
172
+
173
+ default:
174
+ this.isPending.next(false)
175
+ return 0
176
+ }
177
+
178
+ }),
179
+ catchError(err => {
180
+ return throwError(() => err)
181
+ })
182
+ )
183
+ }
184
+
185
+ private handleFinalize(): (source: Observable<any>) => Observable<any> {
186
+ return finalize(() => this.isPending.next(false));
187
+ }
188
+
189
+ private downloadFile(file:string, fileData: any) {
190
+
191
+ const navigatorAny = window.navigator as any
192
+
193
+ const extension = file.split('.')[1].toLowerCase()
194
+
195
+ var newBlob = new Blob([fileData], { type: this.createFileType(extension) })
196
+
197
+ if (navigatorAny.msSaveOrOpenBlob) {
198
+ navigatorAny.msSaveOrOpenBlob(newBlob, file)
199
+ } else {
200
+ const link = document.createElement('a')
201
+ const url = window.URL.createObjectURL(newBlob)
202
+ link.href = url
203
+ link.download = file
204
+ link.click()
205
+ window.URL.revokeObjectURL(url)
206
+ }
207
+
208
+ }
209
+
210
+ private createFileType(ext: any): string {
211
+
212
+ let fileType: string = ""
213
+
214
+ if (ext == 'pdf' || ext == 'csv') {
215
+ fileType = `application/${ext}`
216
+ }
217
+ else if (ext == 'jpeg' || ext == 'jpg' || ext == 'png') {
218
+ fileType = `image/${ext}`
219
+ }
220
+ else if (ext == 'txt') {
221
+ fileType = 'text/plain'
222
+ }
223
+
224
+ else if (ext == 'ppt' || ext == 'pot' || ext == 'pps' || ext == 'ppa') {
225
+ fileType = 'application/vnd.ms-powerpoint'
226
+ }
227
+ else if (ext == 'pptx') {
228
+ fileType = 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
229
+ }
230
+ else if (ext == 'doc' || ext == 'dot') {
231
+ fileType = 'application/msword'
232
+ }
233
+ else if (ext == 'docx') {
234
+ fileType = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
235
+ }
236
+ else if (ext == 'xls' || ext == 'xlt' || ext == 'xla') {
237
+ fileType = 'application/vnd.ms-excel'
238
+ }
239
+ else if (ext == 'xlsx') {
240
+ fileType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
241
+ }
242
+
243
+ return fileType
244
+
245
+ }
246
+
247
+ private combineHeaders(headers: any, isStreaming: boolean) {
248
+
249
+ return (isStreaming) ?
250
+ {
251
+ ...headers,
252
+ observe: 'events',
253
+ responseType: 'text',
254
+ reportProgress: true,
255
+ Accept: 'text/event-stream'
256
+ }
257
+ : headers
258
+
259
+ }
260
+
261
+ }
@@ -0,0 +1,17 @@
1
+ import { Observable, defer, interval } from 'rxjs';
2
+ import { takeWhile, map, tap } from 'rxjs/operators';
3
+
4
+ export function countdown(duration: number): Observable<number> {
5
+
6
+ return defer(() => {
7
+
8
+ const currentCount = { current: duration }
9
+
10
+ return interval(1000).pipe(
11
+ map(() => --currentCount.current),
12
+ takeWhile(count => count >= 0)
13
+ )
14
+
15
+ })
16
+
17
+ }
@@ -0,0 +1,16 @@
1
+ import { Observable, timer } from 'rxjs';
2
+ import { retry } from 'rxjs/operators';
3
+
4
+ const DEFAULT_MAX_RETRIES = 3;
5
+
6
+ export function delayedRetry<T>(delayMs: number, maxRetry = DEFAULT_MAX_RETRIES) {
7
+ return (src: Observable<T>) =>
8
+ src.pipe(
9
+ retry({
10
+ count: maxRetry,
11
+ delay: () => timer(delayMs)
12
+ })
13
+ );
14
+ }
15
+
16
+
@@ -0,0 +1,21 @@
1
+ import { BehaviorSubject, Observable, interval } from 'rxjs';
2
+ import { mergeMap, startWith, takeUntil, tap } from 'rxjs/operators';
3
+
4
+ /**
5
+ * @param pollInterval
6
+ * @param stopCondition$
7
+ * @param isPending$
8
+ */
9
+
10
+ export function requestPolling<T>(pollInterval: number, stopCondition$: Observable<any>, isPending$: BehaviorSubject<boolean>) {
11
+ return (source: Observable<T>): Observable<T> => {
12
+ return interval(pollInterval * 1000)
13
+ .pipe(
14
+ startWith(0),
15
+ tap(() => isPending$.next(true)),
16
+ mergeMap(() => source),
17
+ tap(() => isPending$.next(false)),
18
+ takeUntil(stopCondition$),
19
+ );
20
+ };
21
+ }
@@ -0,0 +1,32 @@
1
+ import { OperatorFunction } from 'rxjs';
2
+ import { filter, map } from 'rxjs/operators';
3
+ import { HttpEventType } from '@angular/common/http';
4
+
5
+ export function requestStreaming(): OperatorFunction<any, any> {
6
+
7
+ return input$ => input$.pipe(
8
+ filter((event: any) =>
9
+ event.type === HttpEventType.DownloadProgress || event.type === HttpEventType.Response
10
+ ),
11
+
12
+ map((event: any) => {
13
+
14
+ if (event.type === HttpEventType.DownloadProgress) {
15
+ return event.partialText || ''
16
+ } else if (event.type === HttpEventType.Response) {
17
+ return event.body
18
+ }
19
+
20
+ }),
21
+
22
+ map((data: any) => {
23
+ if (typeof data === 'string') {
24
+ const matches = data.match(/{[^}]+}/g) || []
25
+ return (matches.length > 0) ? matches.map(match => JSON.parse(match)) : data
26
+ }
27
+ return data
28
+ })
29
+ )
30
+
31
+ }
32
+