http-request-manager 18.7.20 → 18.7.21

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 (197) hide show
  1. package/ARCHITECTURE.md +483 -0
  2. package/DATABASE_README.md +1176 -0
  3. package/HTTP_MANAGER_README.md +579 -0
  4. package/HTTP_SINGNALS_MANAGER_README.md +654 -0
  5. package/HTTP_STATE_MANAGER_README.md +948 -0
  6. package/INTERCEPTOR_README.md +549 -0
  7. package/LOCAL_STORAGE_README.md +1056 -0
  8. package/STORE_STATE_MANAGER_README.md +1322 -0
  9. package/UTILS_README.md +1186 -0
  10. package/WS_MANAGER_README.md +613 -0
  11. package/ng-package.json +8 -0
  12. package/package.json +1 -12
  13. package/src/lib/http-request-manager.module.ts +132 -0
  14. package/src/lib/http-request-services-demo/database-data-demo/database-data-demo.component.html +65 -0
  15. package/src/lib/http-request-services-demo/database-data-demo/database-data-demo.component.scss +0 -0
  16. package/src/lib/http-request-services-demo/database-data-demo/database-data-demo.component.ts +224 -0
  17. package/src/lib/http-request-services-demo/http-request-services-demo.component.html +114 -0
  18. package/src/lib/http-request-services-demo/http-request-services-demo.component.scss +6 -0
  19. package/src/lib/http-request-services-demo/http-request-services-demo.component.ts +52 -0
  20. package/src/lib/http-request-services-demo/local-storage-demo/local-storage-demo.component.html +195 -0
  21. package/src/lib/http-request-services-demo/local-storage-demo/local-storage-demo.component.scss +17 -0
  22. package/src/lib/http-request-services-demo/local-storage-demo/local-storage-demo.component.ts +206 -0
  23. package/src/lib/http-request-services-demo/local-storage-signals-demo/local-storage-signals-demo.component.html +200 -0
  24. package/src/lib/http-request-services-demo/local-storage-signals-demo/local-storage-signals-demo.component.scss +17 -0
  25. package/src/lib/http-request-services-demo/local-storage-signals-demo/local-storage-signals-demo.component.ts +212 -0
  26. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/download-file/download-file.component.html +53 -0
  27. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/download-file/download-file.component.scss +60 -0
  28. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/download-file/download-file.component.ts +72 -0
  29. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/file-download.module.ts +28 -0
  30. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/file-downloader.component.html +10 -0
  31. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/file-downloader.component.scss +29 -0
  32. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/file-downloader.component.ts +100 -0
  33. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/models/download-labels-model.ts +22 -0
  34. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/spinner/spinner.component.html +8 -0
  35. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/spinner/spinner.component.scss +19 -0
  36. package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/spinner/spinner.component.ts +26 -0
  37. package/src/lib/http-request-services-demo/request-manager-demo/models/app-session.model.ts +30 -0
  38. package/src/lib/http-request-services-demo/request-manager-demo/models/app.model.ts +19 -0
  39. package/src/lib/http-request-services-demo/request-manager-demo/models/get-sample.model.ts +25 -0
  40. package/src/lib/http-request-services-demo/request-manager-demo/models/sample-ai-prompt.ts +19 -0
  41. package/src/lib/http-request-services-demo/request-manager-demo/models/sample-client-details.ts +24 -0
  42. package/src/lib/http-request-services-demo/request-manager-demo/models/sample-client-info.ts +30 -0
  43. package/src/lib/http-request-services-demo/request-manager-demo/models/sample-client.model.ts +49 -0
  44. package/src/lib/http-request-services-demo/request-manager-demo/models/sample-mapper-client-info.ts +33 -0
  45. package/src/lib/http-request-services-demo/request-manager-demo/request-manager-demo.component.html +392 -0
  46. package/src/lib/http-request-services-demo/request-manager-demo/request-manager-demo.component.scss +24 -0
  47. package/src/lib/http-request-services-demo/request-manager-demo/request-manager-demo.component.ts +461 -0
  48. package/src/lib/http-request-services-demo/request-manager-state-demo/request-manager-state-demo.component.html +393 -0
  49. package/src/lib/http-request-services-demo/request-manager-state-demo/request-manager-state-demo.component.scss +24 -0
  50. package/src/lib/http-request-services-demo/request-manager-state-demo/request-manager-state-demo.component.ts +421 -0
  51. package/src/lib/http-request-services-demo/request-manager-state-demo/services/state-manager-demo.service.ts +87 -0
  52. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/services/state-data-request.service.ts +120 -0
  53. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-ai-messaging/ws-ai-messaging.component.css +0 -0
  54. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-ai-messaging/ws-ai-messaging.component.html +3 -0
  55. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-ai-messaging/ws-ai-messaging.component.ts +16 -0
  56. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-chats/ws-chats.component.css +0 -0
  57. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-chats/ws-chats.component.html +3 -0
  58. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-chats/ws-chats.component.ts +16 -0
  59. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-data-control/ws-data-control.component.css +31 -0
  60. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-data-control/ws-data-control.component.html +72 -0
  61. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-data-control/ws-data-control.component.scss +41 -0
  62. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-data-control/ws-data-control.component.spec.ts +205 -0
  63. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-data-control/ws-data-control.component.ts +77 -0
  64. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-messaging/ws-messaging.component.css +11 -0
  65. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-messaging/ws-messaging.component.html +96 -0
  66. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-messaging/ws-messaging.component.spec.ts +31 -0
  67. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-messaging/ws-messaging.component.ts +229 -0
  68. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-notifications/ws-notifications.component.css +30 -0
  69. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-notifications/ws-notifications.component.html +172 -0
  70. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-notifications/ws-notifications.component.spec.ts +31 -0
  71. package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-notifications/ws-notifications.component.ts +239 -0
  72. package/src/lib/http-request-services-demo/request-manager-ws-demo/models/oidc-client.model.ts +31 -0
  73. package/src/lib/http-request-services-demo/request-manager-ws-demo/models/user-data.model.ts +32 -0
  74. package/src/lib/http-request-services-demo/request-manager-ws-demo/request-manager-ws-demo.component.css +0 -0
  75. package/src/lib/http-request-services-demo/request-manager-ws-demo/request-manager-ws-demo.component.html +84 -0
  76. package/src/lib/http-request-services-demo/request-manager-ws-demo/request-manager-ws-demo.component.ts +41 -0
  77. package/src/lib/http-request-services-demo/request-manager-ws-demo/services/index.ts +3 -0
  78. package/src/lib/http-request-services-demo/request-manager-ws-demo/services/message-service-demo.service.ts +83 -0
  79. package/src/lib/http-request-services-demo/request-manager-ws-demo/services/notification-service-demo.service.ts +147 -0
  80. package/src/lib/http-request-services-demo/request-manager-ws-demo/services/state-service-demo.service.ts +158 -0
  81. package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/download-file/download-file.component.html +53 -0
  82. package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/download-file/download-file.component.scss +60 -0
  83. package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/download-file/download-file.component.ts +72 -0
  84. package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/file-download.module.ts +28 -0
  85. package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/file-downloader.component.html +10 -0
  86. package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/file-downloader.component.scss +29 -0
  87. package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/file-downloader.component.ts +100 -0
  88. package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/models/download-labels-model.ts +22 -0
  89. package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/spinner/spinner.component.html +8 -0
  90. package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/spinner/spinner.component.scss +19 -0
  91. package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/spinner/spinner.component.ts +26 -0
  92. package/src/lib/http-request-services-demo/request-signals-manager-demo/models/app-session.model.ts +30 -0
  93. package/src/lib/http-request-services-demo/request-signals-manager-demo/models/app.model.ts +19 -0
  94. package/src/lib/http-request-services-demo/request-signals-manager-demo/models/get-sample.model.ts +25 -0
  95. package/src/lib/http-request-services-demo/request-signals-manager-demo/models/sample-ai-prompt.ts +19 -0
  96. package/src/lib/http-request-services-demo/request-signals-manager-demo/models/sample-client-details.ts +24 -0
  97. package/src/lib/http-request-services-demo/request-signals-manager-demo/models/sample-client-info.ts +30 -0
  98. package/src/lib/http-request-services-demo/request-signals-manager-demo/models/sample-client.model.ts +49 -0
  99. package/src/lib/http-request-services-demo/request-signals-manager-demo/models/sample-mapper-client-info.ts +33 -0
  100. package/src/lib/http-request-services-demo/request-signals-manager-demo/request-signals-manager-demo.component.html +380 -0
  101. package/src/lib/http-request-services-demo/request-signals-manager-demo/request-signals-manager-demo.component.scss +24 -0
  102. package/src/lib/http-request-services-demo/request-signals-manager-demo/request-signals-manager-demo.component.ts +410 -0
  103. package/src/lib/http-request-services-demo/store-state-manager-demo/models/settings.model.ts +28 -0
  104. package/src/lib/http-request-services-demo/store-state-manager-demo/services/settings-state.service.ts +48 -0
  105. package/src/lib/http-request-services-demo/store-state-manager-demo/store-state-manager-demo.component.css +0 -0
  106. package/src/lib/http-request-services-demo/store-state-manager-demo/store-state-manager-demo.component.html +23 -0
  107. package/src/lib/http-request-services-demo/store-state-manager-demo/store-state-manager-demo.component.ts +36 -0
  108. package/src/lib/index.ts +3 -0
  109. package/src/lib/interceptors/credentials.interceptor.ts +16 -0
  110. package/src/lib/interceptors/index.ts +6 -0
  111. package/src/lib/interceptors/models/error-settings.model.ts +22 -0
  112. package/src/lib/interceptors/models/index.ts +2 -0
  113. package/src/lib/interceptors/proxy-debugger.interceptor.ts +46 -0
  114. package/src/lib/interceptors/request-error.interceptor.ts +65 -0
  115. package/src/lib/interceptors/request-header.interceptor.ts +53 -0
  116. package/src/lib/models/config-http-options.model.ts +42 -0
  117. package/src/lib/models/config-local-storage-options.model.ts +27 -0
  118. package/src/lib/models/config-options.model.ts +27 -0
  119. package/src/lib/models/config-token.model.ts +9 -0
  120. package/src/lib/models/data-type.enum.ts +5 -0
  121. package/src/lib/models/database-storage.model.ts +24 -0
  122. package/src/lib/models/index.ts +12 -0
  123. package/src/lib/models/retry-options.model.ts +22 -0
  124. package/src/lib/services/database-manager-service/database.manager.service.ts +262 -0
  125. package/src/lib/services/database-manager-service/db.storage.service.ts +207 -0
  126. package/src/lib/services/database-manager-service/index.ts +4 -0
  127. package/src/lib/services/database-manager-service/models/index.ts +2 -0
  128. package/src/lib/services/database-manager-service/models/table-schema.ts +33 -0
  129. package/src/lib/services/index.ts +12 -0
  130. package/src/lib/services/local-storage-manager-service/index.ts +4 -0
  131. package/src/lib/services/local-storage-manager-service/local-storage-manager.service.spec.ts +71 -0
  132. package/src/lib/services/local-storage-manager-service/local-storage-manager.service.ts +426 -0
  133. package/src/lib/services/local-storage-manager-service/local-storage-signals-manager.service.spec.ts +67 -0
  134. package/src/lib/services/local-storage-manager-service/local-storage-signals-manager.service.ts +345 -0
  135. package/src/lib/services/local-storage-manager-service/models/global-store-options.model.ts +30 -0
  136. package/src/lib/services/local-storage-manager-service/models/index.ts +6 -0
  137. package/src/lib/services/local-storage-manager-service/models/setting-options.model.ts +35 -0
  138. package/src/lib/services/local-storage-manager-service/models/storage-data.model.ts +24 -0
  139. package/src/lib/services/local-storage-manager-service/models/storage-option.model.ts +32 -0
  140. package/src/lib/services/local-storage-manager-service/models/storage-type.enum.ts +5 -0
  141. package/src/lib/services/request-manager-services/README.md +268 -0
  142. package/src/lib/services/request-manager-services/http-manager-signals.service.ts +246 -0
  143. package/src/lib/services/request-manager-services/http-manager.service.spec.ts +232 -0
  144. package/src/lib/services/request-manager-services/http-manager.service.ts +274 -0
  145. package/src/lib/services/request-manager-services/index.ts +8 -0
  146. package/src/lib/services/request-manager-services/request-signals.service.ts +214 -0
  147. package/src/lib/services/request-manager-services/request.service.ts +309 -0
  148. package/src/lib/services/request-manager-services/rxjs-operators/countdown.ts +17 -0
  149. package/src/lib/services/request-manager-services/rxjs-operators/delay-retry.ts +16 -0
  150. package/src/lib/services/request-manager-services/rxjs-operators/index.ts +4 -0
  151. package/src/lib/services/request-manager-services/rxjs-operators/request-polling.ts +35 -0
  152. package/src/lib/services/request-manager-services/rxjs-operators/request-streaming.ts +436 -0
  153. package/src/lib/services/request-manager-state-service/http-manager-state.store.ts +1321 -0
  154. package/src/lib/services/request-manager-state-service/index.ts +3 -0
  155. package/src/lib/services/request-manager-state-service/models/api-request.model.ts +61 -0
  156. package/src/lib/services/request-manager-state-service/models/index.ts +6 -0
  157. package/src/lib/services/request-manager-state-service/models/request-options.model.ts +22 -0
  158. package/src/lib/services/request-manager-state-service/models/stream-type.enum.ts +13 -0
  159. package/src/lib/services/request-manager-state-service/models/ws-options.model.ts +39 -0
  160. package/src/lib/services/store-state-manager-service/index.ts +3 -0
  161. package/src/lib/services/store-state-manager-service/models/index.ts +2 -0
  162. package/src/lib/services/store-state-manager-service/models/state-storage-options.model.ts +24 -0
  163. package/src/lib/services/store-state-manager-service/store-state-manager.service.ts +88 -0
  164. package/src/lib/services/utils/app.service.spec.ts +25 -0
  165. package/src/lib/services/utils/app.service.ts +21 -0
  166. package/src/lib/services/utils/encryption/README.md +79 -0
  167. package/src/lib/services/utils/encryption/asymmetrical-encryption.service.ts +282 -0
  168. package/src/lib/services/utils/encryption/encryption-test.service.ts +39 -0
  169. package/src/lib/services/utils/encryption/index.ts +5 -0
  170. package/src/lib/services/utils/encryption/random.ts +81 -0
  171. package/src/lib/services/utils/encryption/symmetrical-encryption.service.ts +93 -0
  172. package/src/lib/services/utils/headers.service.spec.ts +80 -0
  173. package/src/lib/services/utils/headers.service.ts +18 -0
  174. package/src/lib/services/utils/index.ts +7 -0
  175. package/src/lib/services/utils/object-merger.service.spec.ts +18 -0
  176. package/src/lib/services/utils/object-merger.service.ts +78 -0
  177. package/src/lib/services/utils/path-query.service.spec.ts +117 -0
  178. package/src/lib/services/utils/path-query.service.ts +69 -0
  179. package/src/lib/services/utils/random-color.utils.ts +83 -0
  180. package/src/lib/services/utils/utils.service.spec.ts +165 -0
  181. package/src/lib/services/utils/utils.service.ts +192 -0
  182. package/src/lib/services/ws-manager-service/index.ts +4 -0
  183. package/src/lib/services/ws-manager-service/models/channel-info.model.ts +24 -0
  184. package/src/lib/services/ws-manager-service/models/channel-message-data.model.ts +24 -0
  185. package/src/lib/services/ws-manager-service/models/channel-message.model.ts +24 -0
  186. package/src/lib/services/ws-manager-service/models/communication-type.enum.ts +5 -0
  187. package/src/lib/services/ws-manager-service/models/index.ts +5 -0
  188. package/src/lib/services/ws-manager-service/models/ws-user.model.ts +38 -0
  189. package/src/lib/services/ws-manager-service/services/index.ts +3 -0
  190. package/src/lib/services/ws-manager-service/services/websocket.service.ts +392 -0
  191. package/src/public-api.ts +14 -0
  192. package/tsconfig.lib.json +32 -0
  193. package/tsconfig.lib.prod.json +10 -0
  194. package/tsconfig.spec.json +14 -0
  195. package/fesm2022/http-request-manager.mjs +0 -7633
  196. package/fesm2022/http-request-manager.mjs.map +0 -1
  197. package/types/http-request-manager.d.ts +0 -2277
@@ -0,0 +1,268 @@
1
+ # Request Manager Service Documentation
2
+
3
+ The HTTPManagerService is designed to handle HTTP requests and return Observables, providing an efficient and streamlined way to interact with external APIs or services in your Angular application. This service can be imported and used directly or extended to suit your specific needs.
4
+
5
+ ## Usage
6
+ To utilize the HTTPManagerService, you must import it into your service or component. Alternatively, you can extend the service by defining the required generic type for custom implementations.
7
+
8
+ ### Import Example #1 (Injecting the Service)
9
+
10
+ ```ts
11
+ import { HTTPManagerService } from 'path-to-service';
12
+
13
+ export class DistrictService {
14
+
15
+ httpManagerService = inject(HTTPManagerService);
16
+
17
+ private errorRetry = new BehaviorSubject<{ func: Function, message: string } | null>(null);
18
+ errorRetry$ = this.errorRetry.asObservable();
19
+
20
+ apiRequest = ApiRequest.adapt({
21
+ server: 'nodebff/reporting-common-apis/v1',
22
+ path: ['dimensions','locations'],
23
+ adapter: DistrictData.adapt
24
+ });
25
+
26
+ params = {
27
+ type: 'DISTRICT',
28
+ excludeEcom: true
29
+ };
30
+
31
+ fetchDistrictData(params = this.params) {
32
+
33
+ return this.httpManagerService.getRequest(this.apiRequest, [params])
34
+ .pipe(
35
+ catchError((error: HttpErrorResponse) => {
36
+
37
+ // custom retry logic
38
+ const func = this.fetchDistrictData.bind(this);
39
+ const message = error.message;
40
+ this.errorRetry.next({ func, message });
41
+
42
+ return EMPTY;
43
+ })
44
+ );
45
+
46
+ }
47
+
48
+ }
49
+ ```
50
+
51
+ ### Import Example #1 (Subscribing to the service)
52
+
53
+ - Extending HTTPManagerService:
54
+ The DistrictService extends the HTTPManagerService with a generic type of DistrictData, which allows for reusability and scalability. By extending, the fetchDistrictData method uses the getRequest function provided by the parent class to make the request.
55
+
56
+ ```ts
57
+ export class DistrictService extends HTTPManagerService<DistrictData> {
58
+
59
+ }
60
+ ```
61
+
62
+ - Function to Make the Request:
63
+ The fetchDistrictData() method calls the getRequest function and immediately subscribes to the result. Since it subscribes, the request is made and the result is handled within the data$ observable.
64
+ If an error occurs during the request, the error is caught using catchError. The errorRetry$ observable is updated with the error details, which can be handled in the component or template.
65
+
66
+ ```ts
67
+ codefetchDistrictData() {
68
+
69
+ this.getRequest(this.apiRequest, [this.params])
70
+ .pipe(
71
+ catchError((error: HttpErrorResponse) => {
72
+
73
+ const func = this.fetchDistrictData.bind(this)
74
+ const message = error.message
75
+ this.errorRetry.next({ func, message })
76
+
77
+ return EMPTY
78
+ })
79
+ ).subscribe()
80
+
81
+ }
82
+ ```
83
+
84
+ ### Data Observable:
85
+
86
+ The result of the request is stored in the data$ observable, which is inherited from the parent class (HTTPManagerService). This observable is connected to a component for further usage.
87
+
88
+ ### Component Example:
89
+
90
+ In the component, the data fetched by fetchDistrictData() can be accessed by assigning the result to data$, like this:
91
+
92
+ ```ts
93
+ this.data$ = this.awardsFilterStoresService.fetchData(this.payload)
94
+ ```
95
+
96
+ This data$ observable is then used in the template to display the data asynchronously:htmlCopy code{{ data$ | async }}
97
+
98
+ Template Example:
99
+
100
+ The template uses the Angular async pipe to subscribe and display the data from data$. The async pipe manages the subscription and unsubscription automatically, simplifying the handling of observables in the template:
101
+
102
+ ```html
103
+ <div *ngIf="data$ | async as data">
104
+ <!-- Use data here -->
105
+ </div>
106
+ ```
107
+
108
+ By extending the HTTPManagerService, you benefit from reusable request logic and observables that provide seamless integration with Angular components and templates.
109
+
110
+ ## Key Features of the Service
111
+
112
+ ### Error Handling:
113
+
114
+ The example defines an errorRetry$ observable that captures errors using the catchError operator and enables retry logic. This observable can be utilized in your component templates to handle and display errors, making error management more flexible.
115
+ ApiRequest Configuration:
116
+
117
+ The ApiRequest object encapsulates all the necessary details for making an HTTP request:
118
+
119
+ ```ts
120
+ apiRequest = ApiRequest.adapt({
121
+ server: 'nodebff/reporting-common-apis/v1',
122
+ path: ['dimensions','locations'],
123
+ adapter: DistrictData.adapt
124
+ });
125
+ ```
126
+
127
+ ### ApiRequest Options
128
+
129
+ The following are the available options when configuring an ApiRequest object:
130
+
131
+ ```ts
132
+ apiRequest = ApiRequest.adapt({
133
+ server: string,
134
+ path: any[],
135
+ headers: any,
136
+ adapter?: any,
137
+ mapper?: any,
138
+ polling?: number, // in seconds (undefined | 0 = none)
139
+ retry: RetryOptions,
140
+ stream?: boolean,
141
+ displayError: boolean
142
+ });
143
+ ```
144
+
145
+ - server: The base URL or service endpoint for the API request.
146
+
147
+ - path: Additional paths to append to the base URL for constructing the full API endpoint.
148
+
149
+ - headers: Custom headers to include in the request, provided as an object.
150
+
151
+ - adapter (incoming): A model adapter used to transform incoming data (e.g., DistrictData.adapt).
152
+
153
+ - mapper (outgoing): A model adapter used to map outgoing data before sending it to the server (e.g., DistrictData.mapper).
154
+
155
+ - polling: Enables periodic polling, where the request will be made every specified number of seconds.
156
+
157
+ - retry: Retry logic using RetryOptions, which includes:
158
+ - times: Number of retry attempts.
159
+ - delay: Delay in milliseconds between each retry.
160
+
161
+ - stream: Indicate whether the request expects a stream of data from the server.
162
+ - displayError: Error will be presented as a SnackBar notification with description of error
163
+
164
+ When stream: true, the data$ observable will continuously receive the updated data from the stream. This means that data$ represents the data being streamed from the server, and it will keep updating as new data arrives. You can also apply an adapter to transform the streamed data before it's delivered to data$.
165
+
166
+ For example, if you want to transform the incoming stream data using an adapter, you can specify the adapter in the ApiRequest configuration:
167
+
168
+ ```ts
169
+ apiRequest = ApiRequest.adapt({
170
+ server: 'nodebff/reporting-common-apis/v1',
171
+ path: ['dimensions','locations'],
172
+ adapter: DistrictData.adapt,
173
+ stream: true
174
+ });
175
+ ```
176
+
177
+ In this case, DistrictData.adapt will transform the data from the stream as it updates, ensuring that the data$ observable emits the adapted version of the streamed data.
178
+
179
+ ### Example Breakdown
180
+
181
+ - The DistrictService demonstrates how to set up and use the HTTPManagerService to fetch district data by sending a GET request.
182
+ - It uses the ApiRequest object to define the request configuration, including the API server, endpoint paths, and an adapter for data transformation.
183
+ - The fetchDistrictData function handles errors gracefully by retrying the request when an error occurs, and the errorRetry$ observable is exposed for use in templates if necessary.
184
+ - This setup ensures the service is flexible and ready for expansion, allowing for seamless API integrations with error handling and retry capabilities.
185
+
186
+ ### Additional Observables for Request Status:
187
+
188
+ There are several other observables that can help you understand the status of the request:
189
+
190
+ - countdown$: If polling is active, this property gives feedback on when the next request will take place. It starts from the specified time in seconds and counts down to 0, triggering the next request and restarting the countdown.
191
+
192
+ - error$: This returns any HTTP error that occurs during the request.
193
+
194
+ - isPending$: This boolean value indicates whether the request is pending (true) or has been completed (false).
195
+
196
+ - data$: You can access the data fetched in the request using the data$ observable. This provides the response from the server, which can be used for further processing or displaying in the UI.
197
+
198
+ ## Interceptors
199
+
200
+ There are a few interceptors that may be used in your project that will provide a number of convinces for general use case headers.
201
+
202
+ These are the interceptors that are automatically added to the Module by default
203
+
204
+ 1 - WithCredentialsInterceptor
205
+ 2 - RequestHeadersInterceptor
206
+ 3 - ProxyDebuggerInterceptor
207
+
208
+ ### Credentials-Interceptor
209
+
210
+ This interceptor adds the 'credentials' header to all requests, ensuring cookies are maintained across both the module and its children.
211
+
212
+ `{ withCredentials: true }`
213
+
214
+ ### Proxy-Debugger-Interceptor (Not Imported as Default)
215
+
216
+ The Proxy-Debugger has to be imported into your app module and all proxies defined for checking all http requests.
217
+ If there is an Http request that is being proxied, the interceptor will provide the following information in the console.
218
+
219
+ a) `requestUrl` - current URL used by the request
220
+ b) `payload` - payload in request
221
+ c) `headers` - headers in request
222
+ c) `proxyPath` - proxyPath to replace in requestUrl
223
+ d) `actualPath` - request url will proxy target
224
+
225
+ In your providers for your `app.module.ts` - add the following
226
+
227
+ a) The `ProxyDebuggerInterceptor` interceptor
228
+ b) Proxy Config Object from your `proxy.config.json` file
229
+
230
+ For more information on setting up proxy in Angular please refer to this article
231
+
232
+ [Angular proxy configuration for API calls](https://dev.to/developersmill/angular-proxy-configuration-for-api-calls-130b)
233
+
234
+ Below is a sample proxy-config.json file.
235
+
236
+ ```ts
237
+ { provide: HTTP_INTERCEPTORS, useClass: ProxyDebuggerInterceptor, multi: true },
238
+ {
239
+ provide: PROXY_CONFIG,
240
+ useValue: {
241
+ "/localAPI/*": {
242
+ target: "https://httpbin.org",
243
+ secure: false,
244
+ changeOrigin: true,
245
+ pathRewrite: { "^/localAPI": "" },
246
+ logLevel: "debug",
247
+ },
248
+ "/docs/*": {
249
+ target: "https://anotherapi.com",
250
+ secure: true,
251
+ changeOrigin: false,
252
+ pathRewrite: { "^/api": "" },
253
+ logLevel: "info",
254
+ },
255
+ },
256
+ },
257
+ ```
258
+
259
+ ### Request-Header-Interceptor
260
+
261
+ This interceptor adds the following headers to every request
262
+
263
+ 'Content-Type': 'application/json',
264
+ 'Accept-Language': this.language || 'en-CA',
265
+ 'Current-Date': this.currentDate
266
+
267
+ The language change is detected by the `TranslateService` service from NRGX
268
+ The currentDate format is `YYYY-MM-DD`
@@ -0,0 +1,246 @@
1
+ import { Inject, inject, Injectable, Injector, Optional, signal } from '@angular/core';
2
+ import { HttpErrorResponse } from '@angular/common/http';
3
+ import { 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 { RequestSignalsService } from './request-signals.service'; // 👈 updated
8
+ import { requestPolling, countdown, delayedRetry } from './rxjs-operators';
9
+
10
+ import { ToastColors, ToastDisplay, ToastMessageDisplayService } from 'toast-message-display';
11
+ import { CONFIG_SETTINGS_TOKEN } from '../../models/config-token.model';
12
+ import { ConfigOptions } from '../../models';
13
+ import { ObjectMergerService } from '../utils/object-merger.service';
14
+
15
+ @Injectable({
16
+ providedIn: 'root',
17
+ })
18
+ export class HTTPManagerSignalsService<T> extends RequestSignalsService { // 👈 use signals service
19
+
20
+ toastMessage = inject(ToastMessageDisplayService);
21
+ ng_injector = inject(Injector);
22
+ objectMergerService = inject(ObjectMergerService);
23
+
24
+ // ✅ Replaced BehaviorSubjects with Angular signals
25
+ countdown = signal<number>(0);
26
+ error = signal<string | boolean>(false);
27
+ data = signal<any>(null);
28
+
29
+ private polling$ = new Subject<void>();
30
+
31
+ config = ApiRequest.adapt();
32
+
33
+ constructor(@Optional() @Inject(CONFIG_SETTINGS_TOKEN) private configOptions?: ConfigOptions) {
34
+ super();
35
+ this.config = configOptions
36
+ ? ApiRequest.adapt(configOptions.httpRequestOptions)
37
+ : this.config;
38
+ }
39
+
40
+ // REQUESTS
41
+ getRequest<T>(options?: ApiRequest, params?: any[]) {
42
+ this.isPending.set(true);
43
+ this.data.set(null);
44
+
45
+ const updatedOptions = this.defineReqOptions(options, params);
46
+ const func = this.getRecordRequest;
47
+ const requests = this.createRequest(func, updatedOptions);
48
+
49
+ return this.createObservable<T>(updatedOptions, requests, func.name).pipe(
50
+ tap(data => this.data.set(data)),
51
+ finalize(() => this.isPending.set(false)),
52
+ catchError((err) => {
53
+ if (updatedOptions.displayError) this.handleErrorWithSnackBar(err);
54
+ this.isPending.set(false);
55
+ return this.handleError(err);
56
+ })
57
+ );
58
+ }
59
+
60
+ postRequest<T extends { id?: number|string }>(data: T, options: ApiRequest, params?: any[]) {
61
+ this.isPending.set(true);
62
+ this.data.set(null);
63
+
64
+ const updatedOptions = this.defineReqOptions(options, params);
65
+ const func = this.createRecordRequest;
66
+ const requests = this.createRequest(func, updatedOptions, data);
67
+
68
+ return this.createObservable<T>(updatedOptions, requests, func.name).pipe(
69
+ tap(data => this.data.set(data)),
70
+ finalize(() => this.isPending.set(false)),
71
+ catchError((err) => {
72
+ if (updatedOptions.displayError) this.handleErrorWithSnackBar(err);
73
+ this.isPending.set(false);
74
+ return this.handleError(err);
75
+ })
76
+ );
77
+ }
78
+
79
+ putRequest<T extends { id?: number|string }>(data: T, options: ApiRequest, params?: any[]) {
80
+ this.isPending.set(true);
81
+ this.data.set(null);
82
+
83
+ const updatedOptions = this.defineReqOptions(options, params);
84
+ const func = this.updateRecordRequest;
85
+ const requests = this.createRequest(func, updatedOptions, data);
86
+
87
+ return this.createObservable<T>(updatedOptions, requests, func.name).pipe(
88
+ tap(data => this.data.set(data)),
89
+ finalize(() => this.isPending.set(false)),
90
+ catchError((err) => {
91
+ if (updatedOptions.displayError) this.handleErrorWithSnackBar(err);
92
+ this.isPending.set(false);
93
+ return this.handleError(err);
94
+ })
95
+ );
96
+ }
97
+
98
+ deleteRequest<T>(options: ApiRequest, params?: any[]) {
99
+ this.isPending.set(true);
100
+ this.data.set(null);
101
+
102
+ const updatedOptions = this.defineReqOptions(options, params);
103
+ const func = this.deleteRecordRequest;
104
+ const requests = this.createRequest(func, updatedOptions);
105
+
106
+ return this.createObservable<T>(updatedOptions, requests, func.name).pipe(
107
+ tap(data => this.data.set(data)),
108
+ finalize(() => this.isPending.set(false)),
109
+ catchError((err) => {
110
+ if (updatedOptions.displayError) this.handleErrorWithSnackBar(err);
111
+ this.isPending.set(false);
112
+ return this.handleError(err);
113
+ })
114
+ );
115
+ }
116
+
117
+ downloadRequest<T>(options: ApiRequest, params?: any[], saveAs?: string) {
118
+ this.isPending.set(true);
119
+
120
+ const updatedOptions = this.defineReqOptions(options, params);
121
+ const func = this.downloadFileRequest;
122
+ const requests = this.createRequest(func, updatedOptions);
123
+
124
+ return this.createObservable<T>(updatedOptions, requests, func.name).pipe(
125
+ catchError((err) => {
126
+ this.error.set(true);
127
+ this.isPending.set(false);
128
+ return this.handleError(err);
129
+ })
130
+ );
131
+ }
132
+
133
+ // --- private helpers ---
134
+ private createObservable<T>(options: ApiRequest, request$: Observable<T>, funcName: string) {
135
+ const polling =
136
+ options.polling ? (options.polling > 0 ? true : false) : false;
137
+
138
+ const isPolling =
139
+ polling &&
140
+ !(funcName === 'deleteRecordRequest' ||
141
+ funcName === 'updateRecordRequest' ||
142
+ funcName === 'createRecordRequest');
143
+
144
+ this.polling$.next();
145
+
146
+ const polling$ =
147
+ (isPolling && options.polling) || 0 >= 3
148
+ ? request$.pipe(
149
+ requestPolling((options.polling || 0) + 1, this.polling$, this.isPending),
150
+ tap(() => this.countdown.set(0)),
151
+ tap(() => {
152
+ if (!options.polling) return;
153
+ const count = options.polling ? options.polling : 0;
154
+ countdown(count)
155
+ .pipe(
156
+ map((x: number) => {
157
+ const pollingInSec = options.polling || 0;
158
+ const percentageCompleted = ((pollingInSec - x) / pollingInSec) * 100;
159
+ return Math.round(percentageCompleted);
160
+ })
161
+ )
162
+ .subscribe((countDownValue: number) => {
163
+ this.countdown.set(countDownValue);
164
+ });
165
+ }),
166
+ )
167
+ : request$.pipe(
168
+ catchError((err: any) => {
169
+ if (err instanceof HttpErrorResponse) {
170
+ this.error.set(true);
171
+ return this.handleError(err);
172
+ }
173
+ return throwError(() => err);
174
+ })
175
+ );
176
+
177
+ return polling$.pipe(
178
+ catchError((err: any, caught: Observable<T>) => {
179
+ if (err instanceof HttpErrorResponse) {
180
+ this.error.set(true);
181
+ if (isPolling) this.stopPolling();
182
+ return this.handleError(err);
183
+ }
184
+ return throwError(() => err);
185
+ }),
186
+ options?.retry && options.retry.times > 0
187
+ ? delayedRetry((options.retry.delay || 3) * 1000, (options.retry.times || 0) - 1)
188
+ : (source: Observable<T>) => source
189
+ );
190
+ }
191
+
192
+ private createRequest(func: Function, options: ApiRequest, data?: any | any[]) {
193
+ const dataItem = this.prepareRequestData(options, data, func.name);
194
+ return func.bind(this)(dataItem.options, dataItem.data);
195
+ }
196
+
197
+ private prepareRequestData(options: ApiRequest, data: any, funcName: string) {
198
+ if ((options.mapper && funcName === 'updateRecordRequest') || funcName === 'createRecordRequest') {
199
+ if (options?.mapper) {
200
+ data = options.mapper
201
+ ? Array.isArray(data)
202
+ ? map((item) => options.mapper(item))
203
+ : options.mapper(data)
204
+ : data;
205
+ }
206
+ } else {
207
+ if (options?.adapter) {
208
+ data = Array.isArray(data)
209
+ ? map((item) => options.adapter(item))
210
+ : options.adapter(data);
211
+ }
212
+ }
213
+ return { options: options, data: data };
214
+ }
215
+
216
+ private handleError(error: Response | any) {
217
+ this.error.set(error.message || `${error.status} - ${error.statusText}`);
218
+ return throwError(() => error);
219
+ }
220
+
221
+ private handleErrorWithSnackBar(error: Response | any) {
222
+ const displayError = ToastDisplay.adapt({
223
+ message: error.message || `${error.status} - ${error.statusText}`,
224
+ action: 'OK',
225
+ color: ToastColors.ERROR,
226
+ icon: 'error',
227
+ duration: 5 * 1000,
228
+ });
229
+ this.toastMessage.toastMessage(displayError);
230
+ }
231
+
232
+ private stopPolling() {
233
+ this.isPending.set(false);
234
+ this.polling$.next();
235
+ }
236
+
237
+ private defineReqOptions(options: any, params?: any[]) {
238
+ const req = ApiRequest.adapt(options);
239
+ if (req?.path) req.path = params ? [...req.path, ...params] : req.path;
240
+
241
+ const optionsReq = req ? req : ApiRequest.adapt();
242
+ const updatedOptions = this.objectMergerService.mergeOptions(optionsReq);
243
+
244
+ return updatedOptions;
245
+ }
246
+ }