angular-toolbox 0.11.3 → 0.11.4

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 (211) hide show
  1. package/README.md +1 -1
  2. package/esm2022/lib/core/bridge/app-bridge.mjs +3 -3
  3. package/esm2022/lib/core/error/app-bridge-error.mjs +3 -3
  4. package/esm2022/lib/core/error/http-mock-service-error.mjs +3 -3
  5. package/esm2022/lib/core/error/integrity-error.mjs +3 -3
  6. package/esm2022/lib/core/error/subscription-error.mjs +3 -3
  7. package/esm2022/lib/core/impl/lang/identifiable-component.mjs +3 -3
  8. package/esm2022/lib/core/impl/version/version.impl.mjs +3 -3
  9. package/esm2022/lib/framework/index.mjs +3 -1
  10. package/esm2022/lib/framework/logging/connector/console-log-connector.mjs +48 -0
  11. package/esm2022/lib/framework/logging/connector/default-log-connector.mjs +34 -0
  12. package/esm2022/lib/framework/logging/connector/html-log-connector.mjs +177 -0
  13. package/esm2022/lib/framework/logging/connector/index.mjs +4 -0
  14. package/esm2022/lib/framework/logging/impl/abstract-logger.mjs +100 -0
  15. package/esm2022/lib/framework/logging/impl/index.mjs +3 -0
  16. package/esm2022/lib/framework/logging/impl/log-impl.mjs +28 -0
  17. package/esm2022/lib/framework/logging/index.mjs +4 -0
  18. package/esm2022/lib/framework/logging/util/index.mjs +4 -0
  19. package/esm2022/lib/framework/logging/util/log.builder.mjs +28 -0
  20. package/esm2022/lib/framework/logging/util/log.constant.mjs +24 -0
  21. package/esm2022/lib/framework/logging/util/log.util.mjs +142 -0
  22. package/esm2022/lib/framework/mock/http/core/data-storage.mjs +1 -1
  23. package/esm2022/lib/framework/mock/http/core/response-delay.mjs +9 -0
  24. package/esm2022/lib/framework/mock/http/event/event-target.impl.mjs +15 -1
  25. package/esm2022/lib/framework/mock/http/logging/http-mock-logger.mjs +15 -0
  26. package/esm2022/lib/framework/mock/http/logging/http-mock-logging-metadata.builder.mjs +35 -0
  27. package/esm2022/lib/framework/mock/http/path-to-regexp/escape-to-regexp-string.mjs +3 -3
  28. package/esm2022/lib/framework/mock/http/path-to-regexp/model/lex-token.mjs +3 -3
  29. package/esm2022/lib/framework/mock/http/util/data-storage.builder.mjs +5 -3
  30. package/esm2022/lib/framework/mock/http/util/http-headers.util.mjs +18 -3
  31. package/esm2022/lib/framework/mock/http/util/http-mock-max-delay.mjs +12 -0
  32. package/esm2022/lib/framework/mock/http/util/http-mock-response-delay.util.mjs +33 -0
  33. package/esm2022/lib/framework/mock/http/util/http-mock-response.builder.mjs +45 -9
  34. package/esm2022/lib/framework/mock/http/util/index.mjs +2 -1
  35. package/esm2022/lib/framework/mock/http/xhr/delegate-xhr.mjs +75 -41
  36. package/esm2022/lib/framework/mock/http/xhr/http-mock-factory.impl.mjs +4 -3
  37. package/esm2022/lib/framework/mock/http/xhr/http-mock-factory.mjs +3 -2
  38. package/esm2022/lib/framework/mock/http/xhr/xhr-proxy-impl.mjs +7 -6
  39. package/esm2022/lib/framework/mock/http-monitoring-console/component/console-footer/console-footer.component.mjs +30 -0
  40. package/esm2022/lib/framework/mock/http-monitoring-console/component/console-menu/console-menu.component.mjs +30 -0
  41. package/esm2022/lib/framework/mock/http-monitoring-console/component/http-monitoring-console/http-monitoring-console.component.mjs +140 -0
  42. package/esm2022/lib/framework/mock/http-monitoring-console/component/renderer/icon-renderer/icon-renderer.component.mjs +37 -0
  43. package/esm2022/lib/framework/mock/http-monitoring-console/component/renderer/json-viewer/json-viewer.component.mjs +34 -0
  44. package/esm2022/lib/framework/mock/http-monitoring-console/component/renderer/json-viewer-panel/json-viewer-panel.component.mjs +27 -0
  45. package/esm2022/lib/framework/mock/http-monitoring-console/component/renderer/payload-renderer/payload-renderer.component.mjs +50 -0
  46. package/esm2022/lib/framework/mock/http-monitoring-console/component/renderer/response-body-renderer/response-body-renderer.component.mjs +50 -0
  47. package/esm2022/lib/framework/mock/http-monitoring-console/component/renderer/response-preview-renderer/response-preview-renderer.component.mjs +71 -0
  48. package/esm2022/lib/framework/mock/http-monitoring-console/component/renderer/timing-renderer/timing-renderer.component.mjs +55 -0
  49. package/esm2022/lib/framework/mock/http-monitoring-console/component/request-details/request-details.component.mjs +67 -0
  50. package/esm2022/lib/framework/mock/http-monitoring-console/connector/http-monitoring-console-log-connector.mjs +52 -0
  51. package/esm2022/lib/framework/mock/http-monitoring-console/index.mjs +2 -0
  52. package/esm2022/lib/framework/mock/http-monitoring-console/model/business/atx-console-action-type.mjs +14 -0
  53. package/esm2022/lib/framework/mock/http-monitoring-console/model/business/atx-console-action.mjs +9 -0
  54. package/esm2022/lib/framework/mock/http-monitoring-console/model/business/atx-console-json.mjs +9 -0
  55. package/esm2022/lib/framework/mock/http-monitoring-console/model/business/atx-is-imported-log.mjs +10 -0
  56. package/esm2022/lib/framework/mock/http-monitoring-console/model/business/io/atx-body-dto.mjs +9 -0
  57. package/esm2022/lib/framework/mock/http-monitoring-console/model/business/io/atx-header-dto.mjs +9 -0
  58. package/esm2022/lib/framework/mock/http-monitoring-console/model/business/io/atx-http-log-metadata.dto.mjs +9 -0
  59. package/esm2022/lib/framework/mock/http-monitoring-console/model/business/io/atx-http-log.dto.mjs +9 -0
  60. package/esm2022/lib/framework/mock/http-monitoring-console/model/business/io/atx-http-request-metadata.dto.ts.mjs +9 -0
  61. package/esm2022/lib/framework/mock/http-monitoring-console/model/business/io/atx-http-request.dto.mjs +9 -0
  62. package/esm2022/lib/framework/mock/http-monitoring-console/model/business/io/atx-http-response.dto.mjs +9 -0
  63. package/esm2022/lib/framework/mock/http-monitoring-console/model/business/io/hmfl.mjs +9 -0
  64. package/esm2022/lib/framework/mock/http-monitoring-console/model/service/atx-log-io.service.mjs +77 -0
  65. package/esm2022/lib/framework/mock/http-monitoring-console/model/service/io/body-converter.mjs +22 -0
  66. package/esm2022/lib/framework/mock/http-monitoring-console/model/service/io/body-serializer.mjs +47 -0
  67. package/esm2022/lib/framework/mock/http-monitoring-console/model/service/io/http-request-converter.mjs +44 -0
  68. package/esm2022/lib/framework/mock/http-monitoring-console/model/service/io/http-response-converter.mjs +32 -0
  69. package/esm2022/lib/framework/mock/http-monitoring-console/model/service/io/log-converter.mjs +31 -0
  70. package/esm2022/lib/framework/mock/http-monitoring-console/model/service/io/log-headers-converter.mjs +35 -0
  71. package/esm2022/lib/framework/mock/http-monitoring-console/model/service/io/log-message.util.mjs +19 -0
  72. package/esm2022/lib/framework/mock/http-monitoring-console/model/service/io/log-metadata-converter.mjs +27 -0
  73. package/esm2022/lib/framework/mock/http-monitoring-console/model/service/io/request-metadata-converter.mjs +29 -0
  74. package/esm2022/lib/framework/mock/http-monitoring-console/util/console-body-type.mjs +18 -0
  75. package/esm2022/lib/framework/mock/http-monitoring-console/util/console-type-class.mjs +17 -0
  76. package/esm2022/lib/framework/mock/http-monitoring-console/util/data.util.mjs +75 -0
  77. package/esm2022/lib/framework/mock/http-monitoring-console/util/size.util.mjs +35 -0
  78. package/esm2022/lib/framework/mock/http-monitoring-console/util/url.util.mjs +26 -0
  79. package/esm2022/lib/model/business/index.mjs +2 -1
  80. package/esm2022/lib/model/business/lang/app-bridge-command.mjs +3 -3
  81. package/esm2022/lib/model/business/lang/destroyable.mjs +3 -3
  82. package/esm2022/lib/model/business/lang/identifiable.mjs +3 -3
  83. package/esm2022/lib/model/business/logging/http-mock-logging-constant.enum.mjs +34 -0
  84. package/esm2022/lib/model/business/logging/index.mjs +6 -0
  85. package/esm2022/lib/model/business/logging/log-connector.mjs +9 -0
  86. package/esm2022/lib/model/business/logging/log-level.enum.mjs +35 -0
  87. package/esm2022/lib/model/business/logging/log.mjs +9 -0
  88. package/esm2022/lib/model/business/logging/logger.mjs +2 -0
  89. package/esm2022/lib/model/business/logging/transactional-logger.mjs +9 -0
  90. package/esm2022/lib/model/business/mock/http/fetch-client.mjs +7 -2
  91. package/esm2022/lib/model/business/mock/http/http-method-mock.mjs +1 -1
  92. package/esm2022/lib/model/business/mock/http/http-mock-request-metadata.mjs +9 -0
  93. package/esm2022/lib/model/business/mock/http/index.mjs +3 -1
  94. package/esm2022/lib/model/business/mock/http/logging/http-mock-logging-metadata.mjs +9 -0
  95. package/esm2022/lib/model/business/mock/http/logging/http-mock-logging-prefetch-metadata.mjs +9 -0
  96. package/esm2022/lib/model/business/mock/http/logging/index.mjs +3 -0
  97. package/esm2022/lib/model/service/index.mjs +3 -2
  98. package/esm2022/lib/model/service/logging/index.mjs +2 -0
  99. package/esm2022/lib/model/service/logging/logger-service.mjs +24 -0
  100. package/esm2022/lib/model/service/mock/http/index.mjs +3 -0
  101. package/esm2022/lib/model/service/mock/http/logging/http-mock-logging-service.mjs +110 -0
  102. package/esm2022/lib/model/service/mock/http/logging/index.mjs +2 -0
  103. package/esm2022/lib/model/service/ui/app-bridge.service.mjs +3 -3
  104. package/esm2022/lib/model/service/ui/dark-mode.service.mjs +3 -3
  105. package/esm2022/lib/model/service/version/angular-toolbox-version.service.mjs +3 -3
  106. package/esm2022/lib/util/default-scroll-behavior.mjs +3 -3
  107. package/fesm2022/angular-toolbox.mjs +3112 -1000
  108. package/fesm2022/angular-toolbox.mjs.map +1 -1
  109. package/lib/core/bridge/app-bridge.d.ts +2 -2
  110. package/lib/core/error/app-bridge-error.d.ts +2 -2
  111. package/lib/core/error/http-mock-service-error.d.ts +2 -2
  112. package/lib/core/error/integrity-error.d.ts +2 -2
  113. package/lib/core/error/subscription-error.d.ts +2 -2
  114. package/lib/core/impl/lang/identifiable-component.d.ts +2 -2
  115. package/lib/core/impl/version/version.impl.d.ts +2 -2
  116. package/lib/framework/index.d.ts +2 -0
  117. package/lib/framework/logging/connector/console-log-connector.d.ts +34 -0
  118. package/lib/framework/logging/connector/default-log-connector.d.ts +34 -0
  119. package/lib/framework/logging/connector/html-log-connector.d.ts +72 -0
  120. package/lib/framework/logging/connector/index.d.ts +3 -0
  121. package/lib/framework/logging/impl/abstract-logger.d.ts +69 -0
  122. package/lib/framework/logging/impl/index.d.ts +2 -0
  123. package/lib/framework/logging/impl/log-impl.d.ts +42 -0
  124. package/lib/framework/logging/index.d.ts +3 -0
  125. package/lib/framework/logging/util/index.d.ts +3 -0
  126. package/lib/framework/logging/util/log.builder.d.ts +24 -0
  127. package/lib/framework/logging/util/log.constant.d.ts +23 -0
  128. package/lib/framework/logging/util/log.util.d.ts +48 -0
  129. package/lib/framework/mock/http/core/data-storage.d.ts +6 -1
  130. package/lib/framework/mock/http/core/response-delay.d.ts +23 -0
  131. package/lib/framework/mock/http/event/event-target.impl.d.ts +8 -0
  132. package/lib/framework/mock/http/logging/http-mock-logger.d.ts +14 -0
  133. package/lib/framework/mock/http/logging/http-mock-logging-metadata.builder.d.ts +20 -0
  134. package/lib/framework/mock/http/path-to-regexp/escape-to-regexp-string.d.ts +2 -2
  135. package/lib/framework/mock/http/path-to-regexp/model/lex-token.d.ts +2 -2
  136. package/lib/framework/mock/http/util/data-storage.builder.d.ts +3 -2
  137. package/lib/framework/mock/http/util/http-headers.util.d.ts +10 -0
  138. package/lib/framework/mock/http/util/http-mock-max-delay.d.ts +11 -0
  139. package/lib/framework/mock/http/util/http-mock-response-delay.util.d.ts +22 -0
  140. package/lib/framework/mock/http/util/http-mock-response.builder.d.ts +16 -0
  141. package/lib/framework/mock/http/util/index.d.ts +1 -0
  142. package/lib/framework/mock/http/xhr/delegate-xhr.d.ts +11 -4
  143. package/lib/framework/mock/http/xhr/http-mock-factory.impl.d.ts +3 -1
  144. package/lib/framework/mock/http/xhr/xhr-proxy-impl.d.ts +6 -5
  145. package/lib/framework/mock/http-monitoring-console/component/console-footer/console-footer.component.d.ts +8 -0
  146. package/lib/framework/mock/http-monitoring-console/component/console-menu/console-menu.component.d.ts +21 -0
  147. package/lib/framework/mock/http-monitoring-console/component/http-monitoring-console/http-monitoring-console.component.d.ts +42 -0
  148. package/lib/framework/mock/http-monitoring-console/component/renderer/icon-renderer/icon-renderer.component.d.ts +12 -0
  149. package/lib/framework/mock/http-monitoring-console/component/renderer/json-viewer/json-viewer.component.d.ts +8 -0
  150. package/lib/framework/mock/http-monitoring-console/component/renderer/json-viewer-panel/json-viewer-panel.component.d.ts +7 -0
  151. package/lib/framework/mock/http-monitoring-console/component/renderer/payload-renderer/payload-renderer.component.d.ts +20 -0
  152. package/lib/framework/mock/http-monitoring-console/component/renderer/response-body-renderer/response-body-renderer.component.d.ts +20 -0
  153. package/lib/framework/mock/http-monitoring-console/component/renderer/response-preview-renderer/response-preview-renderer.component.d.ts +27 -0
  154. package/lib/framework/mock/http-monitoring-console/component/renderer/timing-renderer/timing-renderer.component.d.ts +13 -0
  155. package/lib/framework/mock/http-monitoring-console/component/request-details/request-details.component.d.ts +27 -0
  156. package/lib/framework/mock/http-monitoring-console/connector/http-monitoring-console-log-connector.d.ts +40 -0
  157. package/lib/framework/mock/http-monitoring-console/index.d.ts +1 -0
  158. package/lib/framework/mock/http-monitoring-console/model/business/atx-console-action-type.d.ts +12 -0
  159. package/lib/framework/mock/http-monitoring-console/model/business/atx-console-action.d.ts +12 -0
  160. package/lib/framework/mock/http-monitoring-console/model/business/atx-console-json.d.ts +14 -0
  161. package/lib/framework/mock/http-monitoring-console/model/business/atx-is-imported-log.d.ts +9 -0
  162. package/lib/framework/mock/http-monitoring-console/model/business/io/atx-body-dto.d.ts +11 -0
  163. package/lib/framework/mock/http-monitoring-console/model/business/io/atx-header-dto.d.ts +11 -0
  164. package/lib/framework/mock/http-monitoring-console/model/business/io/atx-http-log-metadata.dto.d.ts +18 -0
  165. package/lib/framework/mock/http-monitoring-console/model/business/io/atx-http-log.dto.d.ts +23 -0
  166. package/lib/framework/mock/http-monitoring-console/model/business/io/atx-http-request-metadata.dto.ts.d.ts +32 -0
  167. package/lib/framework/mock/http-monitoring-console/model/business/io/atx-http-request.dto.d.ts +18 -0
  168. package/lib/framework/mock/http-monitoring-console/model/business/io/atx-http-response.dto.d.ts +16 -0
  169. package/lib/framework/mock/http-monitoring-console/model/business/io/hmfl.d.ts +12 -0
  170. package/lib/framework/mock/http-monitoring-console/model/service/atx-log-io.service.d.ts +11 -0
  171. package/lib/framework/mock/http-monitoring-console/model/service/io/body-converter.d.ts +12 -0
  172. package/lib/framework/mock/http-monitoring-console/model/service/io/body-serializer.d.ts +13 -0
  173. package/lib/framework/mock/http-monitoring-console/model/service/io/http-request-converter.d.ts +13 -0
  174. package/lib/framework/mock/http-monitoring-console/model/service/io/http-response-converter.d.ts +13 -0
  175. package/lib/framework/mock/http-monitoring-console/model/service/io/log-converter.d.ts +13 -0
  176. package/lib/framework/mock/http-monitoring-console/model/service/io/log-headers-converter.d.ts +13 -0
  177. package/lib/framework/mock/http-monitoring-console/model/service/io/log-message.util.d.ts +12 -0
  178. package/lib/framework/mock/http-monitoring-console/model/service/io/log-metadata-converter.d.ts +13 -0
  179. package/lib/framework/mock/http-monitoring-console/model/service/io/request-metadata-converter.d.ts +13 -0
  180. package/lib/framework/mock/http-monitoring-console/util/console-body-type.d.ts +16 -0
  181. package/lib/framework/mock/http-monitoring-console/util/console-type-class.d.ts +15 -0
  182. package/lib/framework/mock/http-monitoring-console/util/data.util.d.ts +13 -0
  183. package/lib/framework/mock/http-monitoring-console/util/size.util.d.ts +11 -0
  184. package/lib/framework/mock/http-monitoring-console/util/url.util.d.ts +13 -0
  185. package/lib/model/business/index.d.ts +1 -0
  186. package/lib/model/business/lang/app-bridge-command.d.ts +2 -2
  187. package/lib/model/business/lang/destroyable.d.ts +2 -2
  188. package/lib/model/business/lang/identifiable.d.ts +2 -2
  189. package/lib/model/business/logging/http-mock-logging-constant.enum.d.ts +32 -0
  190. package/lib/model/business/logging/index.d.ts +5 -0
  191. package/lib/model/business/logging/log-connector.d.ts +36 -0
  192. package/lib/model/business/logging/log-level.enum.d.ts +33 -0
  193. package/lib/model/business/logging/log.d.ts +34 -0
  194. package/lib/model/business/logging/logger.d.ts +58 -0
  195. package/lib/model/business/logging/transactional-logger.d.ts +28 -0
  196. package/lib/model/business/mock/http/fetch-client.d.ts +1 -1
  197. package/lib/model/business/mock/http/http-method-mock.d.ts +1 -6
  198. package/lib/model/business/mock/http/http-mock-request-metadata.d.ts +33 -0
  199. package/lib/model/business/mock/http/index.d.ts +2 -0
  200. package/lib/model/business/mock/http/logging/http-mock-logging-metadata.d.ts +15 -0
  201. package/lib/model/business/mock/http/logging/http-mock-logging-prefetch-metadata.d.ts +16 -0
  202. package/lib/model/business/mock/http/logging/index.d.ts +2 -0
  203. package/lib/model/service/index.d.ts +2 -1
  204. package/lib/model/service/logging/index.d.ts +1 -0
  205. package/lib/model/service/logging/logger-service.d.ts +9 -0
  206. package/lib/model/service/mock/http/index.d.ts +2 -0
  207. package/lib/model/service/mock/http/logging/http-mock-logging-service.d.ts +78 -0
  208. package/lib/model/service/mock/http/logging/index.d.ts +1 -0
  209. package/lib/model/service/ui/dark-mode.service.d.ts +2 -2
  210. package/lib/util/default-scroll-behavior.d.ts +2 -2
  211. package/package.json +1 -1
@@ -1,18 +1,20 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, NgModule, EventEmitter, Component, Directive, Output, Input, HostListener, Inject, isDevMode, Optional, inject, Pipe } from '@angular/core';
2
+ import { Injectable, NgModule, EventEmitter, Component, Directive, Output, Input, HostListener, Inject, isDevMode, Optional, inject, ChangeDetectionStrategy, Pipe } from '@angular/core';
3
3
  import * as i1 from '@angular/router';
4
4
  import { RouterModule } from '@angular/router';
5
- import { DOCUMENT, XhrFactory } from '@angular/common';
6
- import { HttpStatusCode, HttpHeaders, HttpErrorResponse, HttpParams, HttpRequest } from '@angular/common/http';
7
- import { from, Observable, of } from 'rxjs';
8
- import * as i1$1 from '@angular/platform-browser';
5
+ import * as i1$1 from '@angular/common';
6
+ import { DOCUMENT, formatDate, XhrFactory, CommonModule, DatePipe, NgStyle } from '@angular/common';
7
+ import { Observable, from, of } from 'rxjs';
8
+ import { HttpHeaders, HttpStatusCode, HttpErrorResponse, HttpResponse, HttpParams, HttpRequest, HttpContextToken, HttpContext } from '@angular/common/http';
9
+ import { HttpMockLoggingService as HttpMockLoggingService$1 } from 'projects/angular-toolbox/src/public-api';
10
+ import * as i1$2 from '@angular/platform-browser';
9
11
 
10
12
  /**
11
13
  * @license
12
14
  * Copyright Pascal ECHEMANN. All Rights Reserved.
13
15
  *
14
- * Use of this source code is governed by an MIT-style license that can be ound in
15
- * fthe LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
16
+ * Use of this source code is governed by an MIT-style license that can be found in
17
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
16
18
  */
17
19
  /**
18
20
  * @private
@@ -37,8 +39,8 @@ class SubscriptionError extends Error {
37
39
  * @license
38
40
  * Copyright Pascal ECHEMANN. All Rights Reserved.
39
41
  *
40
- * Use of this source code is governed by an MIT-style license that can be ound in
41
- * fthe LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
42
+ * Use of this source code is governed by an MIT-style license that can be found in
43
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
42
44
  */
43
45
  /**
44
46
  * @private
@@ -63,8 +65,8 @@ class IntegrityError extends Error {
63
65
  * @license
64
66
  * Copyright Pascal ECHEMANN. All Rights Reserved.
65
67
  *
66
- * Use of this source code is governed by an MIT-style license that can be ound in
67
- * fthe LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
68
+ * Use of this source code is governed by an MIT-style license that can be found in
69
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
68
70
  */
69
71
  /**
70
72
  * @private
@@ -87,8 +89,8 @@ class AppBridgeError extends ReferenceError {
87
89
  * @license
88
90
  * Copyright Pascal ECHEMANN. All Rights Reserved.
89
91
  *
90
- * Use of this source code is governed by an MIT-style license that can be ound in
91
- * fthe LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
92
+ * Use of this source code is governed by an MIT-style license that can be found in
93
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
92
94
  */
93
95
  /**
94
96
  * @private
@@ -305,8 +307,8 @@ const SYMBOL = "symbol";
305
307
  * @license
306
308
  * Copyright Pascal ECHEMANN. All Rights Reserved.
307
309
  *
308
- * Use of this source code is governed by an MIT-style license that can be ound in
309
- * fthe LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
310
+ * Use of this source code is governed by an MIT-style license that can be found in
311
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
310
312
  */
311
313
  /**
312
314
  * @private
@@ -461,8 +463,8 @@ class AbstractSubscriptionManager {
461
463
  * @license
462
464
  * Copyright Pascal ECHEMANN. All Rights Reserved.
463
465
  *
464
- * Use of this source code is governed by an MIT-style license that can be ound in
465
- * fthe LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
466
+ * Use of this source code is governed by an MIT-style license that can be found in
467
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
466
468
  */
467
469
  /**
468
470
  * @private
@@ -543,8 +545,8 @@ class AbstractVersionManager {
543
545
  const LAYERS_VERSION_CONFIG = {
544
546
  major: 0,
545
547
  minor: 11,
546
- patch: 3,
547
- buildTimestamp: 1722599248501,
548
+ patch: 4,
549
+ buildTimestamp: 1724056397828,
548
550
  metadata: "beta"
549
551
  };
550
552
  /**
@@ -994,8 +996,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImpor
994
996
  * @license
995
997
  * Copyright Pascal ECHEMANN. All Rights Reserved.
996
998
  *
997
- * Use of this source code is governed by an MIT-style license that can be ound in
998
- * fthe LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
999
+ * Use of this source code is governed by an MIT-style license that can be found in
1000
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
999
1001
  */
1000
1002
  /**
1001
1003
  * @private
@@ -1277,24 +1279,32 @@ const DARK_MODE_CONFIG = {
1277
1279
  * @license
1278
1280
  * Copyright Pascal ECHEMANN. All Rights Reserved.
1279
1281
  *
1280
- * Use of this source code is governed by an MIT-style license that can be ound in
1281
- * fthe LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1282
+ * Use of this source code is governed by an MIT-style license that can be found in
1283
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1284
+ */
1285
+
1286
+ /**
1287
+ * @license
1288
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
1289
+ *
1290
+ * Use of this source code is governed by an MIT-style license that can be found in
1291
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1282
1292
  */
1283
1293
 
1284
1294
  /**
1285
1295
  * @license
1286
1296
  * Copyright Pascal ECHEMANN. All Rights Reserved.
1287
1297
  *
1288
- * Use of this source code is governed by an MIT-style license that can be ound in
1289
- * fthe LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1298
+ * Use of this source code is governed by an MIT-style license that can be found in
1299
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1290
1300
  */
1291
1301
 
1292
1302
  /**
1293
1303
  * @license
1294
1304
  * Copyright Pascal ECHEMANN. All Rights Reserved.
1295
1305
  *
1296
- * Use of this source code is governed by an MIT-style license that can be ound in
1297
- * fthe LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1306
+ * Use of this source code is governed by an MIT-style license that can be found in
1307
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1298
1308
  */
1299
1309
 
1300
1310
  /**
@@ -1360,6 +1370,11 @@ const DARK_MODE_CONFIG = {
1360
1370
  * Use of this source code is governed by an MIT-style license that can be found in
1361
1371
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1362
1372
  */
1373
+ /**
1374
+ * The markup interface for `Observable` object built from the Fetch API.
1375
+ */
1376
+ class FetchClient extends Observable {
1377
+ }
1363
1378
 
1364
1379
  /**
1365
1380
  * @license
@@ -1468,6 +1483,81 @@ const HTTP_MOCKING_FRAMEWORK_CONFIG = {
1468
1483
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1469
1484
  */
1470
1485
 
1486
+ /**
1487
+ * @license
1488
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
1489
+ *
1490
+ * Use of this source code is governed by an MIT-style license that can be found in
1491
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1492
+ */
1493
+
1494
+ /**
1495
+ * @license
1496
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
1497
+ *
1498
+ * Use of this source code is governed by an MIT-style license that can be found in
1499
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1500
+ */
1501
+
1502
+ /**
1503
+ * @license
1504
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
1505
+ *
1506
+ * Use of this source code is governed by an MIT-style license that can be found in
1507
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1508
+ */
1509
+
1510
+ /**
1511
+ * @license
1512
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
1513
+ *
1514
+ * Use of this source code is governed by an MIT-style license that can be found in
1515
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1516
+ */
1517
+
1518
+ /**
1519
+ * @license
1520
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
1521
+ *
1522
+ * Use of this source code is governed by an MIT-style license that can be found in
1523
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1524
+ */
1525
+
1526
+ /**
1527
+ * @license
1528
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
1529
+ *
1530
+ * Use of this source code is governed by an MIT-style license that can be found in
1531
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1532
+ */
1533
+ /**
1534
+ * Defines the level of an Angular Toolbox log.
1535
+ *
1536
+ */
1537
+ var LogLevel;
1538
+ (function (LogLevel) {
1539
+ /**
1540
+ * Indicates that the log is a basic information message.
1541
+ */
1542
+ LogLevel[LogLevel["INFO"] = 0] = "INFO";
1543
+ /**
1544
+ * Indicates that the log represents a config message.
1545
+ */
1546
+ LogLevel[LogLevel["CONFIG"] = 1] = "CONFIG";
1547
+ /**
1548
+ * Indicates that the log is a warning message.
1549
+ */
1550
+ LogLevel[LogLevel["WARNING"] = 2] = "WARNING";
1551
+ /**
1552
+ * Indicates that the log message represents an error.
1553
+ */
1554
+ LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
1555
+ /**
1556
+ * A special level used by loggers to prevent logs to be processed.
1557
+ */
1558
+ LogLevel[LogLevel["OFF"] = 4] = "OFF";
1559
+ })(LogLevel || (LogLevel = {}));
1560
+
1471
1561
  /**
1472
1562
  * @license
1473
1563
  * Copyright Pascal ECHEMANN. All Rights Reserved.
@@ -1499,8 +1589,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImpor
1499
1589
  * @license
1500
1590
  * Copyright Pascal ECHEMANN. All Rights Reserved.
1501
1591
  *
1502
- * Use of this source code is governed by an MIT-style license that can be ound in
1503
- * fthe LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1592
+ * Use of this source code is governed by an MIT-style license that can be found in
1593
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1504
1594
  */
1505
1595
  // --> Internal constants
1506
1596
  /**
@@ -1768,8 +1858,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImpor
1768
1858
  * @license
1769
1859
  * Copyright Pascal ECHEMANN. All Rights Reserved.
1770
1860
  *
1771
- * Use of this source code is governed by an MIT-style license that can be ound in
1772
- * fthe LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1861
+ * Use of this source code is governed by an MIT-style license that can be found in
1862
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1773
1863
  */
1774
1864
  /**
1775
1865
  * @private
@@ -1843,8 +1933,8 @@ class AppBridge {
1843
1933
  * @license
1844
1934
  * Copyright Pascal ECHEMANN. All Rights Reserved.
1845
1935
  *
1846
- * Use of this source code is governed by an MIT-style license that can be ound in
1847
- * fthe LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1936
+ * Use of this source code is governed by an MIT-style license that can be found in
1937
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
1848
1938
  */
1849
1939
  /**
1850
1940
  * @private
@@ -2180,8 +2270,8 @@ const DOLLAR = "$";
2180
2270
  * @license
2181
2271
  * Copyright Pascal ECHEMANN. All Rights Reserved.
2182
2272
  *
2183
- * Use of this source code is governed by an MIT-style license that can be ound in
2184
- * fthe LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
2273
+ * Use of this source code is governed by an MIT-style license that can be found in
2274
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
2185
2275
  *
2186
2276
  * This source code is derived from the following original source code:
2187
2277
  * - https://github.com/pillarjs/path-to-regexp
@@ -3080,47 +3170,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImpor
3080
3170
  * @license
3081
3171
  * Copyright Pascal ECHEMANN. All Rights Reserved.
3082
3172
  *
3083
- * Use of this source code is governed by an MIT-style license that can be found in
3084
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
3173
+ * Use of this source code is governed by an MIT-style license that can be
3174
+ * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
3085
3175
  */
3086
3176
  /**
3087
- * The definition function for the `@HttpMock` decorator.
3088
- *
3089
- * @param config The `HttpMockConfig` object used to initialize the HTTP Mocking Framework.
3177
+ * The default implementation of the `Log` interface.
3090
3178
  */
3091
- const HttpMock = (config) => {
3092
- return (constructor) => {
3093
- const getMockService = (instance) => {
3094
- return Object.values(instance).find((v) => {
3095
- return (v.hasOwnProperty('type') && v.type === HTTP_MOCK_SERVICE);
3096
- });
3097
- };
3098
- const ngOnInit = constructor.prototype.ngOnInit;
3099
- const ngOnDestroy = constructor.prototype.ngOnDestroy;
3100
- const uiid = config.id || Uuid.build();
3101
- if (!ngOnDestroy)
3102
- throw new ReferenceError("Component must implement the OnDestroy interface.");
3103
- if (!ngOnInit)
3104
- throw new ReferenceError("Component must implement the OnInit interface.");
3105
- if (!config.id)
3106
- config.id = uiid;
3107
- constructor.prototype.ngOnInit = function () {
3108
- const mockService = getMockService(this);
3109
- if (!mockService)
3110
- throw new ReferenceError("No provider found for HttpMockService.");
3111
- mockService.addConfig(config);
3112
- ngOnInit.call(this);
3113
- };
3114
- constructor.prototype.ngOnDestroy = function () {
3115
- const mockService = getMockService(this);
3116
- // An exception is already thrown by the ngOnInit() method when HttpMockService is not provided.
3117
- // Following check statement prevents failure during Unit Testing:
3118
- if (mockService)
3119
- mockService.removeConfig(uiid);
3120
- ngOnDestroy.call(this);
3121
- };
3122
- };
3123
- };
3179
+ class LogImpl {
3180
+ /**
3181
+ * Creates a new `LogImpl` instance.
3182
+ *
3183
+ * @param caller Ahuman readable reference for the invoker associated with this log.
3184
+ * @param message The message associated with this log.
3185
+ * @param level The criticality level of this log.
3186
+ * @param metadata Optional metada associated with this log.
3187
+ */
3188
+ constructor(caller, message, level, metadata) {
3189
+ this.caller = caller;
3190
+ this.message = message;
3191
+ this.level = level;
3192
+ this.metadata = metadata;
3193
+ this.timestamp = Date.now();
3194
+ }
3195
+ }
3124
3196
 
3125
3197
  /**
3126
3198
  * @license
@@ -3130,113 +3202,78 @@ const HttpMock = (config) => {
3130
3202
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
3131
3203
  */
3132
3204
  /**
3133
- * @private
3134
- */
3135
- const OK = "OK";
3136
- /**
3137
- * A statefull builder for creating new `HttpResponseMock` instances.
3205
+ * The default ATX log connector. Allows to process logs silently.
3206
+ * This can be useful for removing logs from production environments, if needed.
3138
3207
  */
3139
- class HttpResponseMockBuilder {
3140
- constructor() {
3141
- /**
3142
- * @private
3143
- */
3144
- this._response = {
3145
- url: null,
3146
- body: null,
3147
- status: HttpStatusCode.Ok,
3148
- statusText: OK,
3149
- error: null,
3150
- delay: 0
3151
- };
3152
- }
3208
+ class DefaultLogConnector {
3153
3209
  /**
3154
- * Sets the body property of the new `HttpResponseMock` instance with the specified `body` value.
3155
- *
3156
- * @param body The value used to set the body property of the new `HttpResponseMock` instance.
3157
- *
3158
- * @returns A reference to this `HttpResponseMockBuilder` instance.
3210
+ * @inheritdoc
3159
3211
  */
3160
- body(body) {
3161
- this._response.body = body;
3162
- return this;
3163
- }
3212
+ destroy() { }
3164
3213
  /**
3165
- * Sets the headers property of the new `HttpResponseMock` instance with the specified `headers` value.
3166
- *
3167
- * @param headers The value used to set the `headers` property of the new `HttpResponseMock` instance.
3168
- *
3169
- * @returns A reference to this `HttpResponseMockBuilder` instance.
3214
+ * @inheritdoc
3170
3215
  */
3171
- headers(headers) {
3172
- this._response.headers = headers;
3173
- return this;
3174
- }
3216
+ init(logList) { }
3175
3217
  /**
3176
- * Sets the `status` property of the new `HttpResponseMock` instance with the specified `status` value.
3177
- *
3178
- * @param status The value used to set the `status` property of the new `HttpResponseMock` instance.
3179
- *
3180
- * @returns A reference to this `HttpResponseMockBuilder` instance.
3218
+ * @inheritdoc
3181
3219
  */
3182
- status(status) {
3183
- this._response.status = status;
3184
- return this;
3185
- }
3220
+ sendLog(log) { }
3186
3221
  /**
3187
- * Sets the `statusText` property of the new `HttpResponseMock` instance with the specified `statusText` value.
3188
- *
3189
- * @param statusText The value used to set the `statusText` property of the new `HttpResponseMock` instance.
3190
- *
3191
- * @returns A reference to this `HttpResponseMockBuilder` instance.
3222
+ * @inheritdoc
3192
3223
  */
3193
- statusText(statusText) {
3194
- this._response.statusText = statusText;
3195
- return this;
3196
- }
3224
+ clearLogs() { }
3197
3225
  /**
3198
- * Sets the `url` property of the new `HttpResponseMock` instance with the specified `url` value.
3199
- *
3200
- * @param url The value used to set the `url` property of the new `HttpResponseMock` instance.
3201
- *
3202
- * @returns A reference to this `HttpResponseMockBuilder` instance.
3226
+ * @inheritdoc
3203
3227
  */
3204
- url(url) {
3205
- this._response.url = url;
3206
- return this;
3228
+ copyLogs() { }
3229
+ }
3230
+
3231
+ /**
3232
+ * @license
3233
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
3234
+ *
3235
+ * Use of this source code is governed by an MIT-style license that can be found in
3236
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
3237
+ */
3238
+ /**
3239
+ * An implementation of the `LogConnector` class that sends logs to the JavaScript
3240
+ * native `console` object.
3241
+ */
3242
+ class ConsoleLogConnector {
3243
+ /**
3244
+ * @inheritdoc
3245
+ */
3246
+ destroy() { }
3247
+ /**
3248
+ * @inheritdoc
3249
+ */
3250
+ init(logList) {
3251
+ logList.forEach(log => this.sendLog(log));
3207
3252
  }
3208
3253
  /**
3209
- * Sets the `delay` property of the new `HttpResponseMock` instance with the specified `timer` duration.
3210
- * Maximum value is `10000` miliseconds (10 seconds).
3211
- *
3212
- * @param timer The value used to set the `delay` property of the new `HttpResponseMock` instance.
3213
- *
3214
- * @returns A reference to this `HttpResponseMockBuilder` instance.
3254
+ * @inheritdoc
3215
3255
  */
3216
- delay(timer = 0) {
3217
- this._response.delay = timer;
3218
- return this;
3256
+ sendLog(log) {
3257
+ const level = log.level;
3258
+ if (level === LogLevel.INFO)
3259
+ return console.info(log);
3260
+ if (level === LogLevel.CONFIG)
3261
+ return console.log(log);
3262
+ if (level === LogLevel.ERROR)
3263
+ return console.error(log);
3264
+ console.warn(log);
3219
3265
  }
3220
3266
  /**
3221
- * Returns a new `HttpResponseMock` instance, built from the properties specified with the
3222
- * `HttpResponseMockBuilder` methods.
3223
- *
3224
- * @param error An optional value used to set the `error` property of the new `HttpResponseMock` instance.
3225
- * The `error` parameter values take precedence over all other properties of the `HttpResponseMock`
3226
- * instance.
3227
- * @returns A new `HttpResponseMock` instance.
3267
+ * @inheritdoc
3228
3268
  */
3229
- response(error = null) {
3230
- this._response.error = error;
3231
- return this._response;
3269
+ clearLogs() {
3270
+ console.clear();
3232
3271
  }
3272
+ /**
3273
+ * Not supported.
3274
+ */
3275
+ copyLogs() { }
3233
3276
  }
3234
- /**
3235
- * A utility function used to create new "chainable" `HttpResponseMockBuilder` instances.
3236
- *
3237
- * @returns A new `HttpResponseMockBuilder` instance.
3238
- */
3239
- const httpResponseMock = () => new HttpResponseMockBuilder();
3240
3277
 
3241
3278
  /**
3242
3279
  * @license
@@ -3246,134 +3283,171 @@ const httpResponseMock = () => new HttpResponseMockBuilder();
3246
3283
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
3247
3284
  */
3248
3285
  /**
3249
- * A statefull builder for creating new `HttpHeaders` instances.
3286
+ * @private
3250
3287
  */
3251
- class HttpHeadersMockBuilder {
3252
- constructor() {
3253
- /**
3254
- * @private
3255
- */
3256
- this._headers = new HttpHeaders();
3257
- }
3258
- /**
3259
- * Sets the `"Cache-Control"` property of the new `HttpHeaders` instance with the specified value.
3260
- *
3261
- * @param value The value used to set the `"Cache-Control"` property of the new `HttpHeaders` instance.
3262
- * Default value is `"no-cache"`.
3288
+ const DIV = "div";
3289
+ /**
3290
+ * @private
3291
+ */
3292
+ const SPAN = "span";
3293
+ /**
3294
+ * @private
3295
+ */
3296
+ const S_LOG_INFO = "atx-log";
3297
+ /**
3298
+ * @private
3299
+ */
3300
+ const S_LOG_CONFIG = "atx-config-log";
3301
+ /**
3302
+ * @private
3303
+ */
3304
+ const S_LOG_ERROR = "atx-error-log";
3305
+ /**
3306
+ * @private
3307
+ */
3308
+ const S_WARN = "atx-warn-log";
3309
+ /**
3310
+ * @private
3311
+ */
3312
+ const S_LOG_TIME = "atx-log-time";
3313
+ /**
3314
+ * @private
3315
+ */
3316
+ const S_LOG_LEVEL = "atx-log-level";
3317
+ /**
3318
+ * @private
3319
+ */
3320
+ const S_LOG_CALLER = "atx-log-caller";
3321
+ /**
3322
+ * @private
3323
+ */
3324
+ const S_LOG_MSG = "atx-log-message";
3325
+ /**
3326
+ * @private
3327
+ */
3328
+ const S_LOG_METADA = "atx-log-metadata";
3329
+ /**
3330
+ * @private
3331
+ */
3332
+ const STYLE_ID = 'atx-log-container-style';
3333
+ /**
3334
+ * An implementation of the `LogConnector` interface that processes logs as HTML renderable elements.
3335
+ */
3336
+ class HtmlLogConnector {
3337
+ /**
3338
+ * Creates a new `HtmlLogConnector` instance.
3263
3339
  *
3264
- * @returns A reference to this `HttpResponseMockBuilder` instance.
3340
+ * @param target The HTML element where the logs will be rendered.
3341
+ * @param injectStyle Indicates whether the ATX default HTML styles are injected into the current document (`true`), or not (`false`).
3265
3342
  */
3266
- cacheControl(value = "no-cache") {
3267
- this.setHeader("Cache-Control", value);
3268
- return this;
3343
+ constructor(target, injectStyle = true) {
3344
+ /**
3345
+ * @private
3346
+ */
3347
+ this._logs = [];
3348
+ this._tgt = target;
3349
+ if (injectStyle)
3350
+ this.injectStyle();
3269
3351
  }
3270
3352
  /**
3271
- * Sets the `"CContent-Type"` property of the new `HttpHeaders` instance with the specified value.
3272
- *
3273
- * @param value The value used to set the `"Content-Type"` property of the new `HttpHeaders` instance.
3274
- * Default value is `"application/json; charset=utf-8"`.
3275
- *
3276
- * @returns A reference to this `HttpResponseMockBuilder` instance.
3353
+ * @inheritdoc
3277
3354
  */
3278
- contentType(value = "application/json; charset=utf-8") {
3279
- this.setHeader("Content-Type", value);
3280
- return this;
3355
+ init(logList) {
3356
+ const len = logList.length - 1;
3357
+ let i = 0;
3358
+ for (; i <= len; ++i)
3359
+ this.sendLog(logList[i]);
3281
3360
  }
3282
3361
  /**
3283
- * Sets the `"Priority"` property of the new `HttpHeaders` instance with the specified value.
3284
- *
3285
- * @param value The value used to set the `"Priority"` property of the new `HttpHeaders` instance.
3286
- * Default value is `"u=0, i"`.
3287
- *
3288
- * @returns A reference to this `HttpResponseMockBuilder` instance.
3362
+ * @inheritdoc
3289
3363
  */
3290
- priority(value = "u=0, i") {
3291
- this.setHeader("Priority", value);
3292
- return this;
3364
+ sendLog(log) {
3365
+ this._logs.push(log);
3366
+ this._tgt.appendChild(this.buildLog(log));
3293
3367
  }
3294
3368
  /**
3295
- * Sets the `"User-Agent"` property of the new `HttpHeaders` instance with the specified value.
3296
- *
3297
- * @param value The value used to set the `"User-Agent"` property of the new `HttpHeaders` instance.
3298
- * Default value is the navigator user agent.
3299
- *
3300
- * @returns A reference to this `HttpResponseMockBuilder` instance.
3369
+ * @inheritdoc
3301
3370
  */
3302
- userAgent(value = null) {
3303
- this.setHeader("User-Agent", value || navigator.userAgent);
3304
- return this;
3371
+ destroy() {
3372
+ this._tgt = null;
3373
+ this._logs.length = 0;
3374
+ this._logs = null;
3375
+ this.deleteStyle();
3305
3376
  }
3306
3377
  /**
3307
- * Sets the `"Accept-Language"` property of the new `HttpHeaders` instance with the specified value.
3308
- *
3309
- * @param value The value used to set the `"Accept-Language"` property of the new `HttpHeaders` instance.
3310
- * Default value is the navigator language.
3311
- *
3312
- * @returns A reference to this `HttpResponseMockBuilder` instance.
3378
+ * @inheritdoc
3313
3379
  */
3314
- acceptLanguage(value = null) {
3315
- this.setHeader("Accept-Language", value || navigator.language);
3316
- return this;
3380
+ clearLogs() {
3381
+ this._logs.length = 0;
3382
+ this._tgt.innerHTML = EMPTY_STRING;
3317
3383
  }
3318
3384
  /**
3319
- * Sets the `"Accept"` property of the new `HttpHeaders` instance with the specified value.
3320
- *
3321
- * @param value The value used to set the `"Accept"` property of the new `HttpHeaders` instance.
3322
- * Default value is `'*\/*'`.
3323
- *
3324
- * @returns A reference to this `HttpResponseMockBuilder` instance.
3385
+ * @inheritdoc
3325
3386
  */
3326
- accept(value = "*/*") {
3327
- this.setHeader("Accept", value);
3328
- return this;
3387
+ copyLogs() {
3388
+ const logs = LogUtil.logListToString(this._logs);
3389
+ navigator.clipboard.writeText(logs);
3329
3390
  }
3330
3391
  /**
3331
- * Sets the `"Accept-Encoding"` property of the new `HttpHeaders` instance with the specified value.
3332
- *
3333
- * @param value The value used to set the `"Accept-Encoding"` property of the new `HttpHeaders` instance.
3334
- * Default value is `"ngzip, deflate, br, zstd"`.
3335
- *
3336
- * @returns A reference to this `HttpResponseMockBuilder` instance.
3392
+ * @private
3337
3393
  */
3338
- acceptEncoding(value = "gzip, deflate, br, zstd") {
3339
- this.setHeader("Accept-Encoding", value);
3340
- return this;
3394
+ buildLog(log) {
3395
+ const d = document.createElement(DIV);
3396
+ d.classList.add(this.getCssClassName(log.level));
3397
+ d.appendChild(this.getSpan(`[${LogUtil.dateToHHMMSS(log.timestamp)}]`, S_LOG_TIME));
3398
+ d.appendChild(this.getSpan(`[${LogUtil.getLevelString(log.level)}]`, S_LOG_LEVEL));
3399
+ d.appendChild(this.getSpan(`[${log.caller}]`, S_LOG_CALLER));
3400
+ d.appendChild(this.getSpan(`[${log.message}]`, S_LOG_MSG));
3401
+ d.appendChild(this.getSpan(LogUtil.metadataToString(log.metadata), S_LOG_METADA));
3402
+ return d;
3341
3403
  }
3342
3404
  /**
3343
- * Sets or modifies a value of the new `HttpHeaders` instance.
3344
- *
3345
- * @param name The header name.
3346
- * @param value The value or values to set or override for the given header.
3347
- *
3348
- * @returns A reference to this `HttpResponseMockBuilder` instance.
3405
+ * @private
3349
3406
  */
3350
- set(name, value) {
3351
- this.setHeader(name, value);
3352
- return this;
3407
+ getCssClassName(level) {
3408
+ if (level === LogLevel.INFO)
3409
+ return S_LOG_INFO;
3410
+ if (level === LogLevel.CONFIG)
3411
+ return S_LOG_CONFIG;
3412
+ if (level === LogLevel.ERROR)
3413
+ return S_LOG_ERROR;
3414
+ return S_WARN;
3353
3415
  }
3354
3416
  /**
3355
- * Return a new `HttpHeaders` instance, built from the properties specified with the
3356
- * `HttpHeadersMockBuilder` methods.
3357
- *
3358
- * @returns A new `HttpHeaders` instance.
3417
+ * @private
3359
3418
  */
3360
- headers() {
3361
- return this._headers;
3419
+ getSpan(value, style = null) {
3420
+ const s = document.createElement(SPAN);
3421
+ if (style)
3422
+ s.classList.add(style);
3423
+ s.innerText = value;
3424
+ return s;
3362
3425
  }
3363
3426
  /**
3364
3427
  * @private
3365
3428
  */
3366
- setHeader(name, value) {
3367
- const values = Array.isArray(value) ? value.join(", ") : value;
3368
- this._headers = this._headers.set(name, values);
3429
+ injectStyle() {
3430
+ const style = document.createElement('style');
3431
+ style.id = STYLE_ID;
3432
+ style.innerHTML = ".atx-log-container{width:100%;background:black;font-family:monospace;font-size:14px;padding:10px 12px}.atx-log,.atx-config-log{color:white}.atx-error-log{color:red}.atx-warn-log{color:gold}.atx-log-metadata{color:#469afa}";
3433
+ this._tgt.classList.add("atx-log-container");
3434
+ this.getHead().appendChild(style);
3435
+ }
3436
+ /**
3437
+ * @private
3438
+ */
3439
+ deleteStyle() {
3440
+ const style = document.getElementById(STYLE_ID);
3441
+ if (style)
3442
+ this.getHead().removeChild(style);
3443
+ }
3444
+ /**
3445
+ * @private
3446
+ */
3447
+ getHead() {
3448
+ return document.getElementsByTagName('head')[0];
3369
3449
  }
3370
3450
  }
3371
- /**
3372
- * A utility function used to create new "chainable" `HttpHeadersMockBuilder` instances.
3373
- *
3374
- * @returns A new `HttpHeadersMockBuilder` instance;
3375
- */
3376
- const httpHeadersMock = () => new HttpHeadersMockBuilder();
3377
3451
 
3378
3452
  /**
3379
3453
  * @license
@@ -3383,84 +3457,92 @@ const httpHeadersMock = () => new HttpHeadersMockBuilder();
3383
3457
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
3384
3458
  */
3385
3459
  /**
3386
- * Defines the possible values for the `responseType` property of the
3387
- * `FetchClientBuilder.buildFetchClient()` method.
3460
+ * A convenient immutable instance of the `DefaultLogConnector` class.
3388
3461
  */
3389
- var FetchClientResponseType;
3390
- (function (FetchClientResponseType) {
3462
+ const DEFAULT_LOG_CONNECTOR = new DefaultLogConnector();
3463
+ /**
3464
+ * The base class for all `Logger` objects.
3465
+ */
3466
+ class AbstractLogger {
3467
+ constructor() {
3468
+ /**
3469
+ * @inheritdoc
3470
+ */
3471
+ this.minLogLevel = LogLevel.INFO;
3472
+ /**
3473
+ * The list of logs sent to this logger.
3474
+ */
3475
+ this.logs = [];
3476
+ /**
3477
+ * The reference to the log connector associated with this logger.
3478
+ */
3479
+ this.logConnector = DEFAULT_LOG_CONNECTOR;
3480
+ }
3391
3481
  /**
3392
- * Allows to return the response as a promise that resolves with an `ArrayBuffer`.
3482
+ * @inheritdoc
3393
3483
  */
3394
- FetchClientResponseType["ARRAY_BUFFER"] = "arrayBuffer";
3484
+ setLogConnector(value) {
3485
+ this.logConnector = value || DEFAULT_LOG_CONNECTOR;
3486
+ this.logConnector.init(this.logs);
3487
+ }
3395
3488
  /**
3396
- * Allows to return the response as a promise that resolves with a `Blob`.
3489
+ * @inheritdoc
3397
3490
  */
3398
- FetchClientResponseType["BLOB"] = "blob";
3491
+ getLogConnector() {
3492
+ return this.logConnector;
3493
+ }
3399
3494
  /**
3400
- * Allows to return the response as a promise that resolves with a `FormData` object.
3495
+ * @inheritdoc
3401
3496
  */
3402
- FetchClientResponseType["FORM_DATA"] = "formData";
3497
+ getLogs() {
3498
+ return this.logs;
3499
+ }
3403
3500
  /**
3404
- * Allows to return the response as a promise which resolves with the result of parsing the body text as JSON.
3501
+ * @inheritdoc
3405
3502
  */
3406
- FetchClientResponseType["JSON"] = "json";
3503
+ info(caller, msg, metadata) {
3504
+ this.addLog(caller, msg, LogLevel.INFO, metadata);
3505
+ }
3407
3506
  /**
3408
- * Allows to return the response as a promise that resolves with a `String`.
3409
- * The response is always decoded using UTF-8.
3507
+ * @inheritdoc
3410
3508
  */
3411
- FetchClientResponseType["TEXT"] = "text";
3509
+ config(caller, msg, metadata) {
3510
+ this.addLog(caller, msg, LogLevel.CONFIG, metadata);
3511
+ }
3412
3512
  /**
3413
- * Allows to return the response as a promise that resolves with a `Response` object.
3513
+ * @inheritdoc
3414
3514
  */
3415
- FetchClientResponseType["RESPONSE"] = "response";
3416
- })(FetchClientResponseType || (FetchClientResponseType = {}));
3417
-
3418
- /**
3419
- * @license
3420
- * Copyright Pascal ECHEMANN. All Rights Reserved.
3421
- *
3422
- * Use of this source code is governed by an MIT-style license that can be found in
3423
- * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
3424
- */
3425
- /**
3426
- * A static utility class for building `FetchClient` objects.
3427
- */
3428
- class FetchClientBuilder {
3515
+ error(caller, msg, metadata) {
3516
+ this.addLog(caller, msg, LogLevel.ERROR, metadata);
3517
+ }
3429
3518
  /**
3430
- * Builds and returns a new `FetchClient` object.
3431
- *
3432
- * @param input The definition of the resource to fetch.
3433
- * @param init The object containing options to configure the request.
3434
- * @param responseType Specifies the type of response for the resource to fetch.
3435
- *
3436
- * @returns A new `FetchClient` object.
3519
+ * @inheritdoc
3437
3520
  */
3438
- static buildFetchClient(input, init = null, responseType = FetchClientResponseType.JSON) {
3439
- return from(fetch(input, init || undefined).then((response) => {
3440
- const rspType = responseType;
3441
- if (response.ok)
3442
- return rspType !== FetchClientResponseType.RESPONSE ? FetchClientBuilder.buildResponseStrategy(response, rspType) : response;
3443
- throw new HttpErrorResponse({
3444
- status: response.status,
3445
- statusText: response.statusText
3446
- });
3447
- }));
3521
+ warn(caller, msg, metadata) {
3522
+ this.addLog(caller, msg, LogLevel.WARNING, metadata);
3523
+ }
3524
+ /**
3525
+ * @inheritdoc
3526
+ */
3527
+ destroy() {
3528
+ this.logConnector = null;
3529
+ this.clearLogs();
3530
+ }
3531
+ /**
3532
+ * @inheritdoc
3533
+ */
3534
+ clearLogs() {
3535
+ this.logs.length = 0;
3448
3536
  }
3449
3537
  /**
3450
3538
  * @private
3451
3539
  */
3452
- static buildResponseStrategy(response, responseType) {
3453
- if (responseType === FetchClientResponseType.JSON)
3454
- return response.json();
3455
- if (responseType === FetchClientResponseType.BLOB)
3456
- return response.blob();
3457
- if (responseType === FetchClientResponseType.FORM_DATA)
3458
- return response.formData();
3459
- if (responseType === FetchClientResponseType.ARRAY_BUFFER)
3460
- return response.arrayBuffer();
3461
- if (responseType === FetchClientResponseType.TEXT)
3462
- return response.text();
3463
- return response.json();
3540
+ addLog(caller, msg, level, metadata) {
3541
+ if (level < this.minLogLevel)
3542
+ return;
3543
+ const log = LogBuilder.build(caller, msg, level, metadata);
3544
+ this.logs.push(log);
3545
+ this.logConnector.sendLog(log);
3464
3546
  }
3465
3547
  }
3466
3548
 
@@ -3472,43 +3554,21 @@ class FetchClientBuilder {
3472
3554
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
3473
3555
  */
3474
3556
  /**
3475
- * @private
3476
- * A utility class used by delegate `XhrProxy` instances to dispatch `ProgressEvent`
3477
- * instances.
3478
- *
3479
- * This class is not exposed.
3557
+ * A static builder that creates new `Log` objects.
3480
3558
  */
3481
- class ProgressEventMock extends ProgressEvent {
3482
- constructor() {
3483
- super(...arguments);
3484
- /**
3485
- * @private
3486
- */
3487
- this._total = NaN;
3488
- /**
3489
- * @private
3490
- */
3491
- this._loaded = 0;
3492
- }
3493
- /**
3494
- * A 64-bit unsigned integer indicating the size, in bytes, of the data already
3495
- * transmitted or processed.
3496
- */
3497
- set total(value) {
3498
- this._total = value;
3499
- }
3500
- get total() {
3501
- return this._total;
3502
- }
3559
+ class LogBuilder {
3503
3560
  /**
3504
- * A 64-bit unsigned integer indicating the total size, in bytes, of the data being
3505
- * transmitted or processed.
3561
+ * Builds and returns a new `Log` object initialized with the specified parameters.
3562
+ *
3563
+ * @param caller The reference to the object that sends the new log.
3564
+ * @param message The message of the new log.
3565
+ * @param level The level of the new log.
3566
+ * @param metadata The optional metadata associated with the new log.
3567
+ *
3568
+ * @returns A new `Log` object
3506
3569
  */
3507
- set loaded(value) {
3508
- this._loaded = value;
3509
- }
3510
- get loaded() {
3511
- return this._loaded;
3570
+ static build(caller, message, level = LogLevel.INFO, metadata) {
3571
+ return new LogImpl(caller, message, level, metadata);
3512
3572
  }
3513
3573
  }
3514
3574
 
@@ -3518,118 +3578,159 @@ class ProgressEventMock extends ProgressEvent {
3518
3578
  *
3519
3579
  * Use of this source code is governed by an MIT-style license that can be found in
3520
3580
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
3581
+ */
3582
+ /**
3583
+ * A convenient string used to identify logs of LogLevel.INFO.
3584
+ */
3585
+ const LOG_INFO_STRING = "INFO";
3586
+ /**
3587
+ * A convenient string used to identify logs of LogLevel.CONFIG.
3588
+ */
3589
+ const LOG_CONFIG_STRING = "CONFIG";
3590
+ /**
3591
+ * A convenient string used to identify logs of LogLevel.WARNING.
3592
+ */
3593
+ const LOG_WARNING_STRING = "WARNING";
3594
+ /**
3595
+ * A convenient string used to identify logs of LogLevel.ERROR.
3596
+ */
3597
+ const LOG_ERROR_STRING = "ERROR";
3598
+
3599
+ /**
3600
+ * @license
3601
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
3521
3602
  *
3522
- * This source code is derived from the following original source code:
3523
- * - https://github.com/benlesh/event-target-polyfill
3524
- * - Copyright (c) 2020 Ben Lesh
3525
- *
3526
- * Use of the original source code is governed by an MIT-style license
3527
- * that can be found in the LICENSE file at
3528
- * https://github.com/benlesh/event-target-polyfill/blob/master/LICENSE
3603
+ * Use of this source code is governed by an MIT-style license that can be found in
3604
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
3529
3605
  */
3530
3606
  /**
3531
3607
  * @private
3532
3608
  */
3533
- const ADD = "addEventListener";
3609
+ const TS_FMT = "HH:MM:SS";
3534
3610
  /**
3535
3611
  * @private
3536
3612
  */
3537
- const REMOVE = "removeEventListener";
3613
+ const SEPARATOR = ", ";
3538
3614
  /**
3539
3615
  * @private
3540
- * A utility class the provides an implementation for the `EventTarget` interface.
3541
- * This class is used internally by the framework; please do not expose it.
3542
- *
3543
- * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
3544
3616
  */
3545
- class EventTargetImpl {
3617
+ const R_BRACKET = "[";
3618
+ /**
3619
+ * @private
3620
+ */
3621
+ const L_BRACKET = "]";
3622
+ /**
3623
+ * @private
3624
+ */
3625
+ const LOCALE = "en-us";
3626
+ /**
3627
+ * @private
3628
+ */
3629
+ const getStringEnd = (cusror, size) => {
3630
+ return cusror !== size ? SEPARATOR : EMPTY_STRING;
3631
+ };
3632
+ /**
3633
+ * A convenient utility class for formatting logs.
3634
+ */
3635
+ class LogUtil {
3546
3636
  /**
3547
- * @private
3637
+ * Turns the specified log list into a human redeable string.
3638
+ *
3639
+ * @param logList The list of logs to format.
3640
+ * @returns The formatted log list.
3548
3641
  */
3549
- constructor() {
3550
- this._listenerList = new Map();
3642
+ static logListToString(logList) {
3643
+ const len = logList.length - 1, getLevelString = LogUtil.getLevelString;
3644
+ let logs = EMPTY_STRING, i = 0, levelTxt = EMPTY_STRING;
3645
+ for (; i <= len; ++i) {
3646
+ const log = logList[i];
3647
+ logs += `[${LogUtil.dateToHHMMSS(log.timestamp)}][${getLevelString(log.level)}][${log.caller}][${log.message}]${LogUtil.metadataToString(log.metadata)}\n`;
3648
+ }
3649
+ return logs;
3551
3650
  }
3552
3651
  /**
3553
- * @private
3554
- * Sets up a function that will be called whenever the specified event is delivered to the target.
3555
- *
3556
- * @param type a case-sensitive string representing the event type to listen for.
3557
- * @param listener the object that receives a notification (an object that implements the
3558
- * `Event` interface) when an event of the specified type occurs.
3559
- * @param options an object that specifies characteristics about the event listener.
3652
+ * Turns the specified log level into a human redeable string.
3560
3653
  *
3561
- * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
3654
+ * @param level The log level to format.
3655
+ * @returns The formatted log level.
3562
3656
  */
3563
- addEventListener(type, listener, options) {
3564
- this.checkArgLength(arguments.length, ADD);
3565
- const ll = this._listenerList;
3566
- if (!ll.has(type))
3567
- ll.set(type, new Map());
3568
- const listenersForType = ll.get(type);
3569
- if (!listenersForType.has(listener)) {
3570
- // Any given listener is only registered once
3571
- listenersForType.set(listener, options);
3572
- }
3657
+ static getLevelString(level) {
3658
+ if (level === LogLevel.INFO)
3659
+ return LOG_INFO_STRING;
3660
+ if (level === LogLevel.CONFIG)
3661
+ return LOG_CONFIG_STRING;
3662
+ if (level === LogLevel.WARNING)
3663
+ return LOG_WARNING_STRING;
3664
+ if (level === LogLevel.ERROR)
3665
+ return LOG_ERROR_STRING;
3666
+ return EMPTY_STRING;
3573
3667
  }
3574
3668
  /**
3575
- * @private
3576
- * Removes an event listener previously registered with `EventTarget.addEventListener()` from the target.
3577
- *
3578
- * @param type a case-sensitive which specifies the type of event for which to remove an event listener.
3579
- * @param listener the event listener function of the event handler to remove from the event target.
3580
- * @param options An options object that specifies characteristics about the event listener.
3669
+ * Return a string that represents the specified metadata object.
3581
3670
  *
3582
- * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
3671
+ * @param obj The metadata object to format.
3672
+ * @returns A string that represents the specified metadata object.
3583
3673
  */
3584
- removeEventListener(type, listener, options) {
3585
- this.checkArgLength(arguments.length, REMOVE);
3586
- const ll = this._listenerList;
3587
- if (ll.has(type)) {
3588
- const listenersForType = ll.get(type);
3589
- if (listenersForType.has(listener))
3590
- listenersForType.delete(listener);
3674
+ static metadataToString(obj) {
3675
+ let result = EMPTY_STRING;
3676
+ if (!obj)
3677
+ return result;
3678
+ if (Array.isArray(obj))
3679
+ return LogUtil.formatArray(obj);
3680
+ const keys = Object.keys(obj), len = keys.length - 1;
3681
+ let i = 0;
3682
+ for (; i <= len; ++i) {
3683
+ const key = keys[i];
3684
+ const value = obj[key];
3685
+ if (value === null)
3686
+ result += `${key}=null${getStringEnd(i, len)}`;
3687
+ else if (value === undefined)
3688
+ result += `${key}=undefined${getStringEnd(i, len)}`;
3689
+ else if (typeof value === STRING)
3690
+ result += `${key}="${value}"${getStringEnd(i, len)}`;
3691
+ else if (Array.isArray(value))
3692
+ result += `${key}=${LogUtil.formatArray(value)}${getStringEnd(i, len)}`;
3693
+ else if (typeof value === OBJECT)
3694
+ result += `${key}=${LogUtil.metadataToString(value)}${getStringEnd(i, len)}`;
3695
+ else
3696
+ result += `${key}=${value}${getStringEnd(i, len)}`;
3697
+ }
3698
+ ;
3699
+ if (result.endsWith(SEPARATOR)) {
3700
+ result = result.slice(0, -2);
3591
3701
  }
3702
+ return result !== EMPTY_STRING ? R_BRACKET + result + L_BRACKET : result;
3592
3703
  }
3593
3704
  /**
3594
- * @private
3595
- * Sends an `Event` to this to the `Event` object, (synchronously) invoking the affected event listeners
3596
- * in the appropriate order.
3597
- *
3598
- * @param event the `Event object to dispatch. Its Event.target property will be set to the current EventTarget.
3599
- * @returns true since there are no cancellable events on a base `EventTarget`.
3705
+ * Returns a string that represents the specified timestamp in form `"HH:MM:SS"`.
3600
3706
  *
3601
- * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent
3707
+ * @param timestamp The timestamp to format.
3708
+ * @returns A string that represents the specified timestamp in form `"HH:MM:SS"`.
3602
3709
  */
3603
- dispatchEvent(event) {
3604
- if (!(event instanceof Event)) {
3605
- throw new TypeError("Failed to execute 'dispatchEvent' on 'EventTarget': parameter 1 is not of type 'Event'.");
3606
- }
3607
- const type = event.type;
3608
- const ll = this._listenerList;
3609
- const listenersForType = ll.get(type);
3610
- if (!listenersForType)
3611
- return true;
3612
- for (const listnerEntry of listenersForType.entries()) {
3613
- const listener = listnerEntry[0];
3614
- const options = listnerEntry[1];
3615
- // Listener functions must be executed with the EventTarget as the `this` context.
3616
- if (typeof listener === FUNCTION)
3617
- listener.call(this, event);
3618
- // Listener objects have their handleEvent method called, if they have one
3619
- else if (listener && typeof listener.handleEvent === FUNCTION)
3620
- listener.handleEvent(event);
3621
- if (options && options.once)
3622
- listenersForType.delete(listener);
3623
- }
3624
- return true;
3710
+ static dateToHHMMSS(timestamp) {
3711
+ return formatDate(timestamp, TS_FMT, LOCALE);
3625
3712
  }
3626
3713
  /**
3627
- * @private
3714
+ * Returns a string that represents the specified array.
3715
+ *
3716
+ * @param array The array to format.
3717
+ * @returns A tring that represents the specified array.
3628
3718
  */
3629
- checkArgLength(argLen, method) {
3630
- if (argLen < 2) {
3631
- throw new TypeError(`TypeError: Failed to execute '${method}' on 'EventTarget': 2 arguments required, but ${argLen === 1 ? 'only 1' : '0'} present.`);
3719
+ static formatArray(array) {
3720
+ const len = array.length - 1;
3721
+ let i = 0, result = EMPTY_STRING;
3722
+ for (; i <= len; ++i) {
3723
+ const value = array[i];
3724
+ if (typeof value === STRING)
3725
+ result += `"${value}"${getStringEnd(i, len)}`;
3726
+ else if (Array.isArray(value))
3727
+ result += `${LogUtil.formatArray(value)}${getStringEnd(i, len)}`;
3728
+ else if (typeof value === OBJECT)
3729
+ result += `${LogUtil.metadataToString(value)}${getStringEnd(i, len)}`;
3730
+ else
3731
+ result += `${value}${getStringEnd(i, len)}`;
3632
3732
  }
3733
+ return `[${result}]`;
3633
3734
  }
3634
3735
  }
3635
3736
 
@@ -3642,118 +3743,44 @@ class EventTargetImpl {
3642
3743
  */
3643
3744
  /**
3644
3745
  * @private
3746
+ * The `Logger` implementation used by the `HttpMockLoggingService` class to manage logs.
3747
+ */
3748
+ class HttpMockLogger extends AbstractLogger {
3749
+ }
3750
+
3751
+ /**
3752
+ * @license
3753
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
3645
3754
  *
3646
- * Elemenets marked as "Useless" are never invoked by the Angular framework.
3755
+ * Use of this source code is governed by an MIT-style license that can be found in
3756
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
3647
3757
  */
3648
- class XhrBase extends EventTargetImpl {
3649
- constructor() {
3650
- super(...arguments);
3651
- /**
3652
- * @private
3653
- *
3654
- * XMLHTTPRequest API
3655
- */
3656
- this.UNSENT = 0;
3657
- /**
3658
- * @private
3659
- *
3660
- * XMLHTTPRequest API
3661
- */
3662
- this.OPENED = 1;
3663
- /**
3664
- * @private
3665
- *
3666
- * XMLHTTPRequest API
3667
- */
3668
- this.HEADERS_RECEIVED = 2;
3669
- /**
3670
- * @private
3671
- *
3672
- * XMLHTTPRequest API
3673
- */
3674
- this.LOADING = 3;
3675
- /**
3676
- * @private
3677
- *
3678
- * XMLHTTPRequest API
3679
- */
3680
- this.DONE = 4;
3681
- /**
3682
- * @private
3683
- *
3684
- * XMLHTTPRequest API
3685
- */
3686
- this.withCredentials = false;
3687
- /**
3688
- * @private
3689
- *
3690
- * XMLHTTPRequest API - Useless
3691
- */
3692
- this.onabort = null;
3693
- /**
3694
- * @private
3695
- *
3696
- * XMLHTTPRequest API - Useless
3697
- */
3698
- this.onerror = null;
3699
- /**
3700
- * @private
3701
- *
3702
- * XMLHTTPRequest API - Useless
3703
- */
3704
- this.onload = null;
3705
- /**
3706
- * @private
3707
- *
3708
- * XMLHTTPRequest API - Useless
3709
- */
3710
- this.onloadend = null;
3711
- /**
3712
- * @private
3713
- *
3714
- * XMLHTTPRequest API - Useless
3715
- */
3716
- this.onloadstart = null;
3717
- /**
3718
- * @private
3719
- *
3720
- * XMLHTTPRequest API - Useless
3721
- */
3722
- this.onprogress = null;
3723
- /**
3724
- * @private
3725
- *
3726
- * XMLHTTPRequest API - Useless
3727
- */
3728
- this.onreadystatechange = null;
3729
- /**
3730
- * @private
3731
- *
3732
- * XMLHTTPRequest API - Useless
3733
- */
3734
- this.ontimeout = null;
3735
- }
3758
+ /**
3759
+ * A utility enum that stores constants used by the `HttpMockLoggingService` to create log messages.
3760
+ */
3761
+ var HttpMockLoggingConstant;
3762
+ (function (HttpMockLoggingConstant) {
3736
3763
  /**
3737
3764
  * @private
3738
- *
3739
- * XMLHTTPRequest API - Useless
3765
+ * The "caller" reference for all logs of the HTTP Mocking Framework.
3740
3766
  */
3741
- get responseXML() {
3742
- return null;
3743
- }
3767
+ HttpMockLoggingConstant["CALLER"] = "HTTP Mocking Framework";
3744
3768
  /**
3745
3769
  * @private
3746
- *
3747
- * XMLHTTPRequest API - Useless
3770
+ * The "message" reference for all valid logs of the HTTP Mocking Framework.
3748
3771
  */
3749
- overrideMimeType(mime) { }
3772
+ HttpMockLoggingConstant["RESPONSE_MESSAGE"] = "HTTP response";
3750
3773
  /**
3751
3774
  * @private
3752
- *
3753
- * XMLHTTPRequest API - Useless
3775
+ * The "message" reference for all error logs of the HTTP Mocking Framework.
3754
3776
  */
3755
- getResponseHeader(name) { return null; }
3756
- }
3777
+ HttpMockLoggingConstant["ERROR_MESSAGE"] = "HTTP error";
3778
+ /**
3779
+ * @private
3780
+ * The "message" reference for all prefetch logs of the HTTP Mocking Framework.
3781
+ */
3782
+ HttpMockLoggingConstant["CONFIG_MESSAGE"] = "HTTP prefetch";
3783
+ })(HttpMockLoggingConstant || (HttpMockLoggingConstant = {}));
3757
3784
 
3758
3785
  /**
3759
3786
  * @license
@@ -3764,50 +3791,102 @@ class XhrBase extends EventTargetImpl {
3764
3791
  */
3765
3792
  /**
3766
3793
  * @private
3767
- * Internal reference to a new line character.
3768
- */
3769
- const NL = "\n";
3770
- /**
3771
- * @private
3772
- * A set of static utilities for manipulating `HttpHeaders` objects.
3794
+ *
3795
+ * The utility service that manages the HTTP Mocking Framework logs.
3773
3796
  */
3774
- class HttpHeadersUtil {
3797
+ class HttpMockLoggingService {
3798
+ /**
3799
+ * Returns the number of logs currently processed by this logger.
3800
+ */
3801
+ get size() {
3802
+ return this._logger.getLogs().length;
3803
+ }
3775
3804
  /**
3776
3805
  * @private
3777
- * Returns a string representation the the specified `HttpHeaders `object, compatible with the format
3778
- * expected by the `XMLHttpRequest.getAllResponseHeaders()` method.
3806
+ */
3807
+ constructor() {
3808
+ this._logger = new HttpMockLogger();
3809
+ }
3810
+ /**
3811
+ * Processes information logs with the specified metadata.
3779
3812
  *
3780
- * @param headers The `HttpHeaders` object to format.
3813
+ * @param metadata The metadata associated with the HTTP method to log.
3781
3814
  *
3782
- * @returns A string compatible with the format expected by the `XMLHttpRequest.getAllResponseHeaders()` method.
3815
+ * @return The log for the specified metadata.
3783
3816
  */
3784
- static stringify(headers) {
3785
- let result = EMPTY_STRING;
3786
- if (!headers)
3787
- return result;
3788
- const keys = headers.keys();
3789
- const last = keys.length - 1;
3790
- keys.forEach((key, index) => {
3791
- result += `${key}: ${headers.getAll(key)}${index !== last ? NL : EMPTY_STRING}`;
3792
- });
3793
- return result;
3817
+ info(metadata) {
3818
+ this._logger.info(HttpMockLoggingConstant.CALLER, HttpMockLoggingConstant.RESPONSE_MESSAGE, metadata);
3819
+ return this.getLastLog();
3794
3820
  }
3795
3821
  /**
3796
- * @private
3797
- * Creates the default `HttpHeaders` object for a mocked HTTP request.
3822
+ * Processes error logs with the specified metadata.
3798
3823
  *
3799
- * @returns The default `HttpHeaders` object for a mocked HTTP request.
3824
+ * @param metadata The metadata associated with the HTTP method to log.
3825
+ *
3826
+ * @return The log for the specified metadata.
3800
3827
  */
3801
- static createDefaultRequestHeaders() {
3802
- // "Accept" header is set by Angular framework when missing
3803
- return httpHeadersMock().cacheControl()
3804
- .acceptEncoding()
3805
- .acceptLanguage()
3806
- .priority()
3807
- .userAgent()
3808
- .headers();
3828
+ error(metadata) {
3829
+ this._logger.error(HttpMockLoggingConstant.CALLER, HttpMockLoggingConstant.ERROR_MESSAGE, metadata);
3830
+ return this.getLastLog();
3831
+ }
3832
+ /**
3833
+ * Processes a special kind of logs that are used to indicate that a HTTP operation
3834
+ * started and no response is available yet.
3835
+ *
3836
+ * @param metadata The metadata associated with the HTTP method to log.
3837
+ */
3838
+ prefetch(metadata) {
3839
+ this._logger.config(HttpMockLoggingConstant.CALLER, HttpMockLoggingConstant.CONFIG_MESSAGE, metadata);
3840
+ }
3841
+ /**
3842
+ * @inheritdoc
3843
+ */
3844
+ clearLogs() {
3845
+ this._logger.clearLogs();
3846
+ this._logger.getLogConnector().clearLogs();
3847
+ }
3848
+ /**
3849
+ * @inheritdoc
3850
+ */
3851
+ setLogConnector(value) {
3852
+ this._logger.setLogConnector(value);
3853
+ }
3854
+ /**
3855
+ * @inheritdoc
3856
+ */
3857
+ getLogConnector() {
3858
+ return this._logger.getLogConnector();
3859
+ }
3860
+ /**
3861
+ * @inheritdoc
3862
+ */
3863
+ destroy() {
3864
+ if (this._logger)
3865
+ this._logger.destroy();
3866
+ this._logger = null;
3867
+ }
3868
+ /**
3869
+ * @inheritdoc
3870
+ */
3871
+ ngOnDestroy() {
3872
+ this.destroy();
3873
+ }
3874
+ /**
3875
+ * @inheritdoc
3876
+ */
3877
+ getLastLog() {
3878
+ const logs = this._logger.getLogs();
3879
+ return logs[logs.length - 1];
3809
3880
  }
3881
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: HttpMockLoggingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3882
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: HttpMockLoggingService, providedIn: 'platform' }); }
3810
3883
  }
3884
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: HttpMockLoggingService, decorators: [{
3885
+ type: Injectable,
3886
+ args: [{
3887
+ providedIn: 'platform'
3888
+ }]
3889
+ }], ctorParameters: () => [] });
3811
3890
 
3812
3891
  /**
3813
3892
  * @license
@@ -3817,31 +3896,18 @@ class HttpHeadersUtil {
3817
3896
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
3818
3897
  */
3819
3898
  /**
3820
- * @private
3821
- * A static utility class for building `DataStorage` objects.
3899
+ * A convenient high-level singleton that implements the `Logger` interface.
3822
3900
  */
3823
- class DataStorageBuilder {
3824
- /**
3825
- * @private
3826
- * Builds and returns a new `DataStorage` objects.
3827
- *
3828
- * @param httpResponse The `HttpResponseMock` to be stored by the framework.
3829
- * @param data The data of the HTTP response to be stored by the framework.
3830
- *
3831
- * @returns A new `DataStorage` object.
3832
- */
3833
- static buildDataStorage(httpResponse, data) {
3834
- // TODO: add support for different data types (string, Blob, etc.)
3835
- const stringifiedData = data ? JSON.stringify(data) : EMPTY_STRING;
3836
- return {
3837
- httpResponse: httpResponse,
3838
- loaded: 0,
3839
- total: data ? new Blob([stringifiedData]).size : 0,
3840
- data: data,
3841
- stringifiedData: stringifiedData
3842
- };
3843
- }
3901
+ class LoggerService extends AbstractLogger {
3902
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: LoggerService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
3903
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: LoggerService, providedIn: 'root' }); }
3844
3904
  }
3905
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: LoggerService, decorators: [{
3906
+ type: Injectable,
3907
+ args: [{
3908
+ providedIn: 'root'
3909
+ }]
3910
+ }] });
3845
3911
 
3846
3912
  /**
3847
3913
  * @license
@@ -3851,500 +3917,2340 @@ class DataStorageBuilder {
3851
3917
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
3852
3918
  */
3853
3919
  /**
3854
- * @private
3855
- * The maximum value for a delayed HTTP response.
3856
- */
3857
- const MAX_TIMER = 10000;
3858
- /**
3859
- * @private
3860
- * Intenal "onreadystatechange" event.
3920
+ * The definition function for the `@HttpMock` decorator.
3921
+ *
3922
+ * @param config The `HttpMockConfig` object used to initialize the HTTP Mocking Framework.
3861
3923
  */
3862
- const READY_STATE_CHANGE_EVENT = new Event("onreadystatechange");
3924
+ const HttpMock = (config) => {
3925
+ return (constructor) => {
3926
+ const getMockService = (instance) => {
3927
+ return Object.values(instance).find((v) => {
3928
+ return (v.hasOwnProperty('type') && v.type === HTTP_MOCK_SERVICE);
3929
+ });
3930
+ };
3931
+ const ngOnInit = constructor.prototype.ngOnInit;
3932
+ const ngOnDestroy = constructor.prototype.ngOnDestroy;
3933
+ const uiid = config.id || Uuid.build();
3934
+ if (!ngOnDestroy)
3935
+ throw new ReferenceError("Component must implement the OnDestroy interface.");
3936
+ if (!ngOnInit)
3937
+ throw new ReferenceError("Component must implement the OnInit interface.");
3938
+ if (!config.id)
3939
+ config.id = uiid;
3940
+ constructor.prototype.ngOnInit = function () {
3941
+ const mockService = getMockService(this);
3942
+ if (!mockService)
3943
+ throw new ReferenceError("No provider found for HttpMockService.");
3944
+ mockService.addConfig(config);
3945
+ ngOnInit.call(this);
3946
+ };
3947
+ constructor.prototype.ngOnDestroy = function () {
3948
+ const mockService = getMockService(this);
3949
+ // An exception is already thrown by the ngOnInit() method when HttpMockService is not provided.
3950
+ // Following check statement prevents failure during Unit Testing:
3951
+ if (mockService)
3952
+ mockService.removeConfig(uiid);
3953
+ ngOnDestroy.call(this);
3954
+ };
3955
+ };
3956
+ };
3957
+
3863
3958
  /**
3864
- * @private
3959
+ * @license
3960
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
3961
+ *
3962
+ * Use of this source code is governed by an MIT-style license that can be found in
3963
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
3865
3964
  */
3866
- const EVT_PROPS_CONFIG = { writable: false, value: this };
3867
3965
  /**
3868
- * @private
3869
- * A utility class used as delegate of `XMLHttpRequest` functionalities when
3870
- * a HTTP request is intercepted by the Mocking Framework .
3966
+ * A statefull builder for creating new `HttpHeaders` instances.
3871
3967
  */
3872
- class DelegateXhr extends XhrBase {
3873
- /**
3874
- * Returns the response body content.
3875
- *
3876
- * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/response
3877
- */
3878
- get response() {
3879
- return this._dataStorage?.data || null;
3968
+ class HttpHeadersMockBuilder {
3969
+ constructor() {
3970
+ /**
3971
+ * @private
3972
+ */
3973
+ this._headers = new HttpHeaders();
3880
3974
  }
3881
3975
  /**
3882
- * Returns the numerical HTTP status code of the `XMLHttpRequest` response.
3976
+ * Sets the `"Cache-Control"` property of the new `HttpHeaders` instance with the specified value.
3883
3977
  *
3884
- * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/status
3978
+ * @param value The value used to set the `"Cache-Control"` property of the new `HttpHeaders` instance.
3979
+ * Default value is `"no-cache"`.
3980
+ *
3981
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
3885
3982
  */
3886
- get status() {
3887
- return this._status;
3983
+ cacheControl(value = "no-cache") {
3984
+ this.setHeader("Cache-Control", value);
3985
+ return this;
3888
3986
  }
3889
3987
  /**
3890
- * Returns a string containing the response status message as returned by the HTTP server.
3988
+ * Sets the `"CContent-Type"` property of the new `HttpHeaders` instance with the specified value.
3891
3989
  *
3892
- * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/statusText
3990
+ * @param value The value used to set the `"Content-Type"` property of the new `HttpHeaders` instance.
3991
+ * Default value is `"application/json; charset=utf-8"`.
3992
+ *
3993
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
3893
3994
  */
3894
- get statusText() {
3895
- return this._statusText;
3995
+ contentType(value = "application/json; charset=utf-8") {
3996
+ this.setHeader("Content-Type", value);
3997
+ return this;
3896
3998
  }
3897
3999
  /**
3898
- * Returns the state the `XMLHttpRequest` client is in.
4000
+ * Sets the `"Priority"` property of the new `HttpHeaders` instance with the specified value.
3899
4001
  *
3900
- * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/readyState
4002
+ * @param value The value used to set the `"Priority"` property of the new `HttpHeaders` instance.
4003
+ * Default value is `"u=0, i"`.
4004
+ *
4005
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
3901
4006
  */
3902
- get readyState() {
3903
- return this._readyState;
4007
+ priority(value = "u=0, i") {
4008
+ this.setHeader("Priority", value);
4009
+ return this;
3904
4010
  }
3905
4011
  /**
3906
- * Returns the serialized URL of the response or the empty string if the URL is `null`.
4012
+ * Sets the `"User-Agent"` property of the new `HttpHeaders` instance with the specified value.
3907
4013
  *
3908
- * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/responseURL
4014
+ * @param value The value used to set the `"User-Agent"` property of the new `HttpHeaders` instance.
4015
+ * Default value is the navigator user agent.
4016
+ *
4017
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
3909
4018
  */
3910
- get responseURL() {
3911
- return this._url;
4019
+ userAgent(value = null) {
4020
+ this.setHeader("User-Agent", value || navigator.userAgent);
4021
+ return this;
3912
4022
  }
3913
4023
  /**
3914
- * Returns the text received from a server following a request being sent.
4024
+ * Sets the `"Accept-Language"` property of the new `HttpHeaders` instance with the specified value.
3915
4025
  *
3916
- * Throws an `InvalidStateError` DOMException if responseType is not the empty string or "text".
4026
+ * @param value The value used to set the `"Accept-Language"` property of the new `HttpHeaders` instance.
4027
+ * Default value is the navigator language.
3917
4028
  *
3918
- * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/responseText
4029
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
3919
4030
  */
3920
- get responseText() {
3921
- return this._dataStorage?.stringifiedData || EMPTY_STRING;
4031
+ acceptLanguage(value = null) {
4032
+ this.setHeader("Accept-Language", value || navigator.language);
4033
+ return this;
3922
4034
  }
3923
4035
  /**
3924
- * Returns an `XMLHttpRequestUpload` object that can be observed to monitor an upload progress.
4036
+ * Sets the `"Accept"` property of the new `HttpHeaders` instance with the specified value.
3925
4037
  *
3926
- * @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/upload
4038
+ * @param value The value used to set the `"Accept"` property of the new `HttpHeaders` instance.
4039
+ * Default value is `'*\/*'`.
4040
+ *
4041
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
3927
4042
  */
3928
- get upload() {
3929
- return null;
4043
+ accept(value = "*/*") {
4044
+ this.setHeader("Accept", value);
4045
+ return this;
3930
4046
  }
3931
4047
  /**
3932
- * @private
4048
+ * Sets the `"Accept-Encoding"` property of the new `HttpHeaders` instance with the specified value.
4049
+ *
4050
+ * @param value The value used to set the `"Accept-Encoding"` property of the new `HttpHeaders` instance.
4051
+ * Default value is `"ngzip, deflate, br, zstd"`.
4052
+ *
4053
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
3933
4054
  */
3934
- open(method, url, async, username, password) {
3935
- this._method = method;
3936
- this._url = url;
3937
- this.setReadyState(this.OPENED);
4055
+ acceptEncoding(value = "gzip, deflate, br, zstd") {
4056
+ this.setHeader("Accept-Encoding", value);
4057
+ return this;
3938
4058
  }
3939
4059
  /**
3940
- * Aborts the request if it has already been sent. When a request is aborted, its `readyState`
3941
- * is changed to `XMLHttpRequest.UNSENT` and the request status code is set to `0`.
4060
+ * Sets or modifies a value of the new `HttpHeaders` instance.
4061
+ *
4062
+ * @param name The header name.
4063
+ * @param value The value or values to set or override for the given header.
4064
+ *
4065
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
3942
4066
  */
3943
- abort() {
3944
- this._readyState = this.UNSENT;
3945
- this._status = 0;
3946
- this.eventDispatch("abort");
4067
+ set(name, value) {
4068
+ this.setHeader(name, value);
4069
+ return this;
3947
4070
  }
3948
4071
  /**
3949
- * Returns all the response headers, separated by CRLF, as a string, or returns `null`
3950
- * if no response has been received.
4072
+ * Return a new `HttpHeaders` instance, built from the properties specified with the
4073
+ * `HttpHeadersMockBuilder` methods.
3951
4074
  *
3952
- * @returns All the response headers, separated by CRLF, as a string, or returns `null`
3953
- * if no response has been received.
4075
+ * @returns A new `HttpHeaders` instance.
3954
4076
  */
3955
- getAllResponseHeaders() {
3956
- return this._dataStorage ? HttpHeadersUtil.stringify(this._headers) : EMPTY_STRING;
4077
+ headers() {
4078
+ return this._headers;
3957
4079
  }
3958
4080
  /**
3959
- * Sends the request to the server.
3960
- *
3961
- * @param body A body of data to be sent in the XHR request.
4081
+ * @private
3962
4082
  */
3963
- send(body) {
3964
- const request = this.buildHttpRequest(body);
4083
+ setHeader(name, value) {
4084
+ const values = Array.isArray(value) ? value.join(", ") : value;
4085
+ this._headers = this._headers.set(name, values);
4086
+ }
4087
+ }
4088
+ /**
4089
+ * A utility function used to create new "chainable" `HttpHeadersMockBuilder` instances.
4090
+ *
4091
+ * @returns A new `HttpHeadersMockBuilder` instance;
4092
+ */
4093
+ const httpHeadersMock = () => new HttpHeadersMockBuilder();
4094
+
4095
+ /**
4096
+ * @license
4097
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
4098
+ *
4099
+ * Use of this source code is governed by an MIT-style license that can be found in
4100
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4101
+ */
4102
+ /**
4103
+ * @private
4104
+ * Internal reference to a new line character.
4105
+ */
4106
+ const CRLF = "\r\n";
4107
+ /**
4108
+ * @private
4109
+ * A set of static utilities for manipulating `HttpHeaders` objects.
4110
+ */
4111
+ class HttpHeadersUtil {
4112
+ /**
4113
+ * @private
4114
+ * Returns a string representation the the specified `HttpHeaders `object, compatible with the format
4115
+ * expected by the `XMLHttpRequest.getAllResponseHeaders()` method.
4116
+ *
4117
+ * @param headers The `HttpHeaders` object to format.
4118
+ *
4119
+ * @returns A string compatible with the format expected by the `XMLHttpRequest.getAllResponseHeaders()` method.
4120
+ */
4121
+ static stringify(headers) {
4122
+ let result = EMPTY_STRING;
4123
+ if (!headers)
4124
+ return result;
4125
+ const keys = headers.keys();
4126
+ const last = keys.length - 1;
4127
+ keys.forEach((key, index) => {
4128
+ result += `${key}: ${headers.getAll(key)}${index !== last ? CRLF : EMPTY_STRING}`;
4129
+ });
4130
+ return result;
4131
+ }
4132
+ /**
4133
+ * @private
4134
+ * Returns a `HttpHeaders` object built from the string returns by the `XMLHttpRequest.getAllResponseHeaders()` method,
4135
+ * or `null` wheher `XMLHttpRequest.getAllResponseHeaders()` return `null`.
4136
+ *
4137
+ * @param value The string to turn into a `HttpHeaders `object.
4138
+ *
4139
+ * @returns A `HttpHeaders` object, or `null`.
4140
+ */
4141
+ static encode(value) {
4142
+ if (value === null)
4143
+ return null;
4144
+ return new HttpHeaders(value);
4145
+ }
4146
+ /**
4147
+ * @private
4148
+ * Creates the default `HttpHeaders` object for a mocked HTTP request.
4149
+ *
4150
+ * @returns The default `HttpHeaders` object for a mocked HTTP request.
4151
+ */
4152
+ static createDefaultRequestHeaders() {
4153
+ // "Accept" header is set by Angular framework when missing
4154
+ return httpHeadersMock().cacheControl()
4155
+ .acceptEncoding()
4156
+ .acceptLanguage()
4157
+ .priority()
4158
+ .userAgent()
4159
+ .headers();
4160
+ }
4161
+ }
4162
+
4163
+ /**
4164
+ * @license
4165
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
4166
+ *
4167
+ * Use of this source code is governed by an MIT-style license that can be found in
4168
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4169
+ */
4170
+ /**
4171
+ * A convenient constant that represents the maximum value for a delayed HTTP response.
4172
+ */
4173
+ const HTTP_MOCK_MAX_DELAY = 10000;
4174
+
4175
+ /**
4176
+ * @license
4177
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
4178
+ *
4179
+ * Use of this source code is governed by an MIT-style license that can be found in
4180
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4181
+ */
4182
+ /**
4183
+ * @private
4184
+ */
4185
+ const OK = "OK";
4186
+ /**
4187
+ * A statefull builder for creating new `HttpResponseMock` instances.
4188
+ */
4189
+ class HttpResponseMockBuilder {
4190
+ constructor() {
4191
+ /**
4192
+ * @private
4193
+ */
4194
+ this._response = {
4195
+ url: null,
4196
+ body: null,
4197
+ status: HttpStatusCode.Ok,
4198
+ statusText: OK,
4199
+ error: null,
4200
+ delay: 0
4201
+ };
4202
+ }
4203
+ /**
4204
+ * Sets the body property of the new `HttpResponseMock` instance with the specified `body` value.
4205
+ *
4206
+ * @param body The value used to set the body property of the new `HttpResponseMock` instance.
4207
+ *
4208
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
4209
+ */
4210
+ body(body) {
4211
+ this._response.body = body;
4212
+ return this;
4213
+ }
4214
+ /**
4215
+ * Sets the headers property of the new `HttpResponseMock` instance with the specified `headers` value.
4216
+ *
4217
+ * @param headers The value used to set the `headers` property of the new `HttpResponseMock` instance.
4218
+ *
4219
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
4220
+ */
4221
+ headers(headers) {
4222
+ this._response.headers = headers;
4223
+ return this;
4224
+ }
4225
+ /**
4226
+ * Add the list of HTTP headers generated by the `HttpHeadersUtil.createDefaultRequestHeaders()`
4227
+ * to the mock response.
4228
+ *
4229
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
4230
+ */
4231
+ defaultHeaders() {
4232
+ const defaultHeaders = HttpHeadersUtil.createDefaultRequestHeaders();
4233
+ let headers = this._response.headers;
4234
+ if (headers) {
4235
+ const keys = defaultHeaders.keys();
4236
+ keys.forEach(key => headers?.append(key, defaultHeaders.get(key)));
4237
+ }
4238
+ else
4239
+ headers = defaultHeaders;
4240
+ this._response.headers = headers;
4241
+ return this;
4242
+ }
4243
+ /**
4244
+ * Sets the `status` property of the new `HttpResponseMock` instance with the specified `status` value.
4245
+ *
4246
+ * @param status The value used to set the `status` property of the new `HttpResponseMock` instance.
4247
+ *
4248
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
4249
+ */
4250
+ status(status) {
4251
+ this._response.status = status;
4252
+ return this;
4253
+ }
4254
+ /**
4255
+ * Sets the `statusText` property of the new `HttpResponseMock` instance with the specified `statusText` value.
4256
+ *
4257
+ * @param statusText The value used to set the `statusText` property of the new `HttpResponseMock` instance.
4258
+ *
4259
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
4260
+ */
4261
+ statusText(statusText) {
4262
+ this._response.statusText = statusText;
4263
+ return this;
4264
+ }
4265
+ /**
4266
+ * Sets the `url` property of the new `HttpResponseMock` instance with the specified `url` value.
4267
+ *
4268
+ * @param url The value used to set the `url` property of the new `HttpResponseMock` instance.
4269
+ *
4270
+ * @returns A reference to this `HttpResponseMockBuilder` instance.
4271
+ */
4272
+ url(url) {
4273
+ this._response.url = url;
4274
+ return this;
4275
+ }
4276
+ /**
4277
+ * @private
4278
+ * Overload implementation
4279
+ */
4280
+ delay(...arg) {
4281
+ if (arg.length <= 1) {
4282
+ let timer = arg[0] || NaN;
4283
+ if (isNaN(timer)) {
4284
+ this._response.delay = HTTP_MOCK_MAX_DELAY - Math.random() * HTTP_MOCK_MAX_DELAY;
4285
+ return this;
4286
+ }
4287
+ if (timer > HTTP_MOCK_MAX_DELAY) {
4288
+ this._response.delay = HTTP_MOCK_MAX_DELAY;
4289
+ return this;
4290
+ }
4291
+ if (timer < 0)
4292
+ timer = 0;
4293
+ this._response.delay = timer;
4294
+ return this;
4295
+ }
4296
+ let min = arg[0], max = arg[1];
4297
+ if (max > HTTP_MOCK_MAX_DELAY)
4298
+ max = HTTP_MOCK_MAX_DELAY;
4299
+ if (min < 0 || min > max)
4300
+ min = 0;
4301
+ this._response.delay = Math.floor(Math.random() * (max - min) + min);
4302
+ return this;
4303
+ }
4304
+ /**
4305
+ * Returns a new `HttpResponseMock` instance, built from the properties specified with the
4306
+ * `HttpResponseMockBuilder` methods.
4307
+ *
4308
+ * @param error An optional value used to set the `error` property of the new `HttpResponseMock` instance.
4309
+ * The `error` parameter values take precedence over all other properties of the `HttpResponseMock`
4310
+ * instance.
4311
+ * @returns A new `HttpResponseMock` instance.
4312
+ */
4313
+ response(error = null) {
4314
+ this._response.error = error;
4315
+ return this._response;
4316
+ }
4317
+ }
4318
+ /**
4319
+ * A utility function used to create new "chainable" `HttpResponseMockBuilder` instances.
4320
+ *
4321
+ * @returns A new `HttpResponseMockBuilder` instance.
4322
+ */
4323
+ const httpResponseMock = () => new HttpResponseMockBuilder();
4324
+
4325
+ /**
4326
+ * @license
4327
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
4328
+ *
4329
+ * Use of this source code is governed by an MIT-style license that can be found in
4330
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4331
+ */
4332
+ /**
4333
+ * Defines the possible values for the `responseType` property of the
4334
+ * `FetchClientBuilder.buildFetchClient()` method.
4335
+ */
4336
+ var FetchClientResponseType;
4337
+ (function (FetchClientResponseType) {
4338
+ /**
4339
+ * Allows to return the response as a promise that resolves with an `ArrayBuffer`.
4340
+ */
4341
+ FetchClientResponseType["ARRAY_BUFFER"] = "arrayBuffer";
4342
+ /**
4343
+ * Allows to return the response as a promise that resolves with a `Blob`.
4344
+ */
4345
+ FetchClientResponseType["BLOB"] = "blob";
4346
+ /**
4347
+ * Allows to return the response as a promise that resolves with a `FormData` object.
4348
+ */
4349
+ FetchClientResponseType["FORM_DATA"] = "formData";
4350
+ /**
4351
+ * Allows to return the response as a promise which resolves with the result of parsing the body text as JSON.
4352
+ */
4353
+ FetchClientResponseType["JSON"] = "json";
4354
+ /**
4355
+ * Allows to return the response as a promise that resolves with a `String`.
4356
+ * The response is always decoded using UTF-8.
4357
+ */
4358
+ FetchClientResponseType["TEXT"] = "text";
4359
+ /**
4360
+ * Allows to return the response as a promise that resolves with a `Response` object.
4361
+ */
4362
+ FetchClientResponseType["RESPONSE"] = "response";
4363
+ })(FetchClientResponseType || (FetchClientResponseType = {}));
4364
+
4365
+ /**
4366
+ * @license
4367
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
4368
+ *
4369
+ * Use of this source code is governed by an MIT-style license that can be found in
4370
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4371
+ */
4372
+ /**
4373
+ * A static utility class for building `FetchClient` objects.
4374
+ */
4375
+ class FetchClientBuilder {
4376
+ /**
4377
+ * Builds and returns a new `FetchClient` object.
4378
+ *
4379
+ * @param input The definition of the resource to fetch.
4380
+ * @param init The object containing options to configure the request.
4381
+ * @param responseType Specifies the type of response for the resource to fetch.
4382
+ *
4383
+ * @returns A new `FetchClient` object.
4384
+ */
4385
+ static buildFetchClient(input, init = null, responseType = FetchClientResponseType.JSON) {
4386
+ return from(fetch(input, init || undefined).then((response) => {
4387
+ const rspType = responseType;
4388
+ if (response.ok)
4389
+ return rspType !== FetchClientResponseType.RESPONSE ? FetchClientBuilder.buildResponseStrategy(response, rspType) : response;
4390
+ throw new HttpErrorResponse({
4391
+ status: response.status,
4392
+ statusText: response.statusText
4393
+ });
4394
+ }));
4395
+ }
4396
+ /**
4397
+ * @private
4398
+ */
4399
+ static buildResponseStrategy(response, responseType) {
4400
+ if (responseType === FetchClientResponseType.JSON)
4401
+ return response.json();
4402
+ if (responseType === FetchClientResponseType.BLOB)
4403
+ return response.blob();
4404
+ if (responseType === FetchClientResponseType.FORM_DATA)
4405
+ return response.formData();
4406
+ if (responseType === FetchClientResponseType.ARRAY_BUFFER)
4407
+ return response.arrayBuffer();
4408
+ if (responseType === FetchClientResponseType.TEXT)
4409
+ return response.text();
4410
+ return response.json();
4411
+ }
4412
+ }
4413
+
4414
+ /**
4415
+ * @license
4416
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
4417
+ *
4418
+ * Use of this source code is governed by an MIT-style license that can be found in
4419
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4420
+ */
4421
+ /**
4422
+ * @private
4423
+ * A utility class used by delegate `XhrProxy` instances to dispatch `ProgressEvent`
4424
+ * instances.
4425
+ *
4426
+ * This class is not exposed.
4427
+ */
4428
+ class ProgressEventMock extends ProgressEvent {
4429
+ constructor() {
4430
+ super(...arguments);
4431
+ /**
4432
+ * @private
4433
+ */
4434
+ this._total = NaN;
4435
+ /**
4436
+ * @private
4437
+ */
4438
+ this._loaded = 0;
4439
+ }
4440
+ /**
4441
+ * A 64-bit unsigned integer indicating the size, in bytes, of the data already
4442
+ * transmitted or processed.
4443
+ */
4444
+ set total(value) {
4445
+ this._total = value;
4446
+ }
4447
+ get total() {
4448
+ return this._total;
4449
+ }
4450
+ /**
4451
+ * A 64-bit unsigned integer indicating the total size, in bytes, of the data being
4452
+ * transmitted or processed.
4453
+ */
4454
+ set loaded(value) {
4455
+ this._loaded = value;
4456
+ }
4457
+ get loaded() {
4458
+ return this._loaded;
4459
+ }
4460
+ }
4461
+
4462
+ /**
4463
+ * @license
4464
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
4465
+ *
4466
+ * Use of this source code is governed by an MIT-style license that can be found in
4467
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4468
+ *
4469
+ * This source code is derived from the following original source code:
4470
+ * - https://github.com/benlesh/event-target-polyfill
4471
+ * - Copyright (c) 2020 Ben Lesh
4472
+ *
4473
+ * Use of the original source code is governed by an MIT-style license
4474
+ * that can be found in the LICENSE file at
4475
+ * https://github.com/benlesh/event-target-polyfill/blob/master/LICENSE
4476
+ */
4477
+ /**
4478
+ * @private
4479
+ */
4480
+ const ADD = "addEventListener";
4481
+ /**
4482
+ * @private
4483
+ */
4484
+ const REMOVE = "removeEventListener";
4485
+ /**
4486
+ * @private
4487
+ * A utility class the provides an implementation for the `EventTarget` interface.
4488
+ * This class is used internally by the framework; please do not expose it.
4489
+ *
4490
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
4491
+ */
4492
+ class EventTargetImpl {
4493
+ /**
4494
+ * @private
4495
+ */
4496
+ constructor() {
4497
+ this._listenerList = new Map();
4498
+ }
4499
+ /**
4500
+ * @private
4501
+ * Sets up a function that will be called whenever the specified event is delivered to the target.
4502
+ *
4503
+ * @param type a case-sensitive string representing the event type to listen for.
4504
+ * @param listener the object that receives a notification (an object that implements the
4505
+ * `Event` interface) when an event of the specified type occurs.
4506
+ * @param options an object that specifies characteristics about the event listener.
4507
+ *
4508
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
4509
+ */
4510
+ addEventListener(type, listener, options) {
4511
+ this.checkArgLength(arguments.length, ADD);
4512
+ const ll = this._listenerList;
4513
+ if (!ll.has(type))
4514
+ ll.set(type, new Map());
4515
+ const listenersForType = ll.get(type);
4516
+ if (!listenersForType.has(listener)) {
4517
+ // Any given listener is only registered once
4518
+ listenersForType.set(listener, options);
4519
+ }
4520
+ }
4521
+ /**
4522
+ * @private
4523
+ * Removes an event listener previously registered with `EventTarget.addEventListener()` from the target.
4524
+ *
4525
+ * @param type a case-sensitive which specifies the type of event for which to remove an event listener.
4526
+ * @param listener the event listener function of the event handler to remove from the event target.
4527
+ * @param options An options object that specifies characteristics about the event listener.
4528
+ *
4529
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
4530
+ */
4531
+ removeEventListener(type, listener, options) {
4532
+ this.checkArgLength(arguments.length, REMOVE);
4533
+ const ll = this._listenerList;
4534
+ if (ll.has(type)) {
4535
+ const listenersForType = ll.get(type);
4536
+ if (listenersForType.has(listener))
4537
+ listenersForType.delete(listener);
4538
+ if (listenersForType.size === 0)
4539
+ ll.delete(type);
4540
+ }
4541
+ }
4542
+ /**
4543
+ * @private
4544
+ * Sends an `Event` to this to the `Event` object, (synchronously) invoking the affected event listeners
4545
+ * in the appropriate order.
4546
+ *
4547
+ * @param event the `Event object to dispatch. Its Event.target property will be set to the current EventTarget.
4548
+ * @returns true since there are no cancellable events on a base `EventTarget`.
4549
+ *
4550
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent
4551
+ */
4552
+ dispatchEvent(event) {
4553
+ if (!(event instanceof Event)) {
4554
+ throw new TypeError("Failed to execute 'dispatchEvent' on 'EventTarget': parameter 1 is not of type 'Event'.");
4555
+ }
4556
+ const type = event.type;
4557
+ const ll = this._listenerList;
4558
+ const listenersForType = ll.get(type);
4559
+ if (!listenersForType)
4560
+ return true;
4561
+ for (const listnerEntry of listenersForType.entries()) {
4562
+ const listener = listnerEntry[0];
4563
+ const options = listnerEntry[1];
4564
+ // Listener functions must be executed with the EventTarget as the `this` context.
4565
+ if (typeof listener === FUNCTION)
4566
+ listener.call(this, event);
4567
+ // Listener objects have their handleEvent method called, if they have one
4568
+ else if (listener && typeof listener.handleEvent === FUNCTION)
4569
+ listener.handleEvent(event);
4570
+ if (options && options.once)
4571
+ listenersForType.delete(listener);
4572
+ if (listenersForType.size === 0)
4573
+ ll.delete(type);
4574
+ }
4575
+ return true;
4576
+ }
4577
+ /**
4578
+ * Checks whether the `EventTarget` object has any listeners registered for a specific type of event.
4579
+ *
4580
+ * @param type The type of event.
4581
+ *
4582
+ * @return A value of `true` if a listener of the specified type is registered; `false` otherwise.
4583
+ */
4584
+ hasEventListener(type) {
4585
+ return this._listenerList.has(type);
4586
+ }
4587
+ /**
4588
+ * @private
4589
+ */
4590
+ checkArgLength(argLen, method) {
4591
+ if (argLen < 2) {
4592
+ throw new TypeError(`TypeError: Failed to execute '${method}' on 'EventTarget': 2 arguments required, but ${argLen === 1 ? 'only 1' : '0'} present.`);
4593
+ }
4594
+ }
4595
+ }
4596
+
4597
+ /**
4598
+ * @license
4599
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
4600
+ *
4601
+ * Use of this source code is governed by an MIT-style license that can be found in
4602
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4603
+ */
4604
+ /**
4605
+ * @private
4606
+ *
4607
+ * Elemenets marked as "Useless" are never invoked by the Angular framework.
4608
+ */
4609
+ class XhrBase extends EventTargetImpl {
4610
+ constructor() {
4611
+ super(...arguments);
4612
+ /**
4613
+ * @private
4614
+ *
4615
+ * XMLHTTPRequest API
4616
+ */
4617
+ this.UNSENT = 0;
4618
+ /**
4619
+ * @private
4620
+ *
4621
+ * XMLHTTPRequest API
4622
+ */
4623
+ this.OPENED = 1;
4624
+ /**
4625
+ * @private
4626
+ *
4627
+ * XMLHTTPRequest API
4628
+ */
4629
+ this.HEADERS_RECEIVED = 2;
4630
+ /**
4631
+ * @private
4632
+ *
4633
+ * XMLHTTPRequest API
4634
+ */
4635
+ this.LOADING = 3;
4636
+ /**
4637
+ * @private
4638
+ *
4639
+ * XMLHTTPRequest API
4640
+ */
4641
+ this.DONE = 4;
4642
+ /**
4643
+ * @private
4644
+ *
4645
+ * XMLHTTPRequest API
4646
+ */
4647
+ this.withCredentials = false;
4648
+ /**
4649
+ * @private
4650
+ *
4651
+ * XMLHTTPRequest API - Useless
4652
+ */
4653
+ this.onabort = null;
4654
+ /**
4655
+ * @private
4656
+ *
4657
+ * XMLHTTPRequest API - Useless
4658
+ */
4659
+ this.onerror = null;
4660
+ /**
4661
+ * @private
4662
+ *
4663
+ * XMLHTTPRequest API - Useless
4664
+ */
4665
+ this.onload = null;
4666
+ /**
4667
+ * @private
4668
+ *
4669
+ * XMLHTTPRequest API - Useless
4670
+ */
4671
+ this.onloadend = null;
4672
+ /**
4673
+ * @private
4674
+ *
4675
+ * XMLHTTPRequest API - Useless
4676
+ */
4677
+ this.onloadstart = null;
4678
+ /**
4679
+ * @private
4680
+ *
4681
+ * XMLHTTPRequest API - Useless
4682
+ */
4683
+ this.onprogress = null;
4684
+ /**
4685
+ * @private
4686
+ *
4687
+ * XMLHTTPRequest API - Useless
4688
+ */
4689
+ this.onreadystatechange = null;
4690
+ /**
4691
+ * @private
4692
+ *
4693
+ * XMLHTTPRequest API - Useless
4694
+ */
4695
+ this.ontimeout = null;
4696
+ }
4697
+ /**
4698
+ * @private
4699
+ *
4700
+ * XMLHTTPRequest API - Useless
4701
+ */
4702
+ get responseXML() {
4703
+ return null;
4704
+ }
4705
+ /**
4706
+ * @private
4707
+ *
4708
+ * XMLHTTPRequest API - Useless
4709
+ */
4710
+ overrideMimeType(mime) { }
4711
+ /**
4712
+ * @private
4713
+ *
4714
+ * XMLHTTPRequest API - Useless
4715
+ */
4716
+ getResponseHeader(name) { return null; }
4717
+ }
4718
+
4719
+ /**
4720
+ * @license
4721
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
4722
+ *
4723
+ * Use of this source code is governed by an MIT-style license that can be found in
4724
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4725
+ */
4726
+ /**
4727
+ * @private
4728
+ * A static utility class for building `DataStorage` objects.
4729
+ */
4730
+ class DataStorageBuilder {
4731
+ /**
4732
+ * @private
4733
+ * Builds and returns a new `DataStorage` objects.
4734
+ *
4735
+ * @param httpResponse The `HttpResponseMock` to be stored by the framework.
4736
+ * @param data The data of the HTTP response to be stored by the framework.
4737
+ * @param metadata The metadata of the HTTP mock request to be stored by the framework.
4738
+ *
4739
+ * @returns A new `DataStorage` object.
4740
+ */
4741
+ static buildDataStorage(httpResponse, data, metadata) {
4742
+ // TODO: add support for different data types (string, Blob, etc.)
4743
+ const stringifiedData = data ? JSON.stringify(data) : EMPTY_STRING;
4744
+ return {
4745
+ httpResponse: httpResponse,
4746
+ loaded: 0,
4747
+ total: data ? new Blob([stringifiedData]).size : 0,
4748
+ data: data,
4749
+ stringifiedData: stringifiedData,
4750
+ requestMetadata: metadata
4751
+ };
4752
+ }
4753
+ }
4754
+
4755
+ /**
4756
+ * @license
4757
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
4758
+ *
4759
+ * Use of this source code is governed by an MIT-style license that can be found in
4760
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4761
+ */
4762
+ /**
4763
+ * @private
4764
+ * A static builder for creating `HttpMockLoggingMetadata` objects.
4765
+ */
4766
+ class HttpMockLoggingMetadataBuilder {
4767
+ /**
4768
+ * @private
4769
+ * Creates and returns a new `HttpMockLoggingMetadata` object.
4770
+ */
4771
+ static build(xhr, request, requestMetadata) {
4772
+ const responseInit = {
4773
+ body: xhr.response,
4774
+ status: xhr.status,
4775
+ statusText: xhr.statusText,
4776
+ url: xhr.responseURL,
4777
+ headers: HttpHeadersUtil.encode(xhr.getAllResponseHeaders())
4778
+ };
4779
+ const response = new HttpResponse(responseInit);
4780
+ return {
4781
+ request: request,
4782
+ response: response,
4783
+ requestMetadata: requestMetadata
4784
+ };
4785
+ }
4786
+ }
4787
+
4788
+ /**
4789
+ * @license
4790
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
4791
+ *
4792
+ * Use of this source code is governed by an MIT-style license that can be found in
4793
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4794
+ */
4795
+ /**
4796
+ * @private
4797
+ * A utility for managing HTTP responses delay.
4798
+ */
4799
+ class HttpMockResponseDelayUtil {
4800
+ /**
4801
+ * @private
4802
+ * A utility function that return a `ResponseDelay` object, depending on the timer parameters.
4803
+ *
4804
+ * @param timer The seed value used to create the `ResponseDelay` object.
4805
+ * @returns A `ResponseDelay` object.
4806
+ */
4807
+ static getResponseDelay(timer) {
4808
+ let duration = timer;
4809
+ if (timer < 0)
4810
+ duration = 0;
4811
+ if (timer > HTTP_MOCK_MAX_DELAY)
4812
+ duration = HTTP_MOCK_MAX_DELAY;
4813
+ return {
4814
+ stalled: Math.random() * duration,
4815
+ duration: duration
4816
+ };
4817
+ }
4818
+ }
4819
+
4820
+ /**
4821
+ * @license
4822
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
4823
+ *
4824
+ * Use of this source code is governed by an MIT-style license that can be found in
4825
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4826
+ */
4827
+ /**
4828
+ * @private
4829
+ * Intenal "onreadystatechange" event.
4830
+ */
4831
+ const READY_STATE_CHANGE_EVENT = new Event("onreadystatechange");
4832
+ /**
4833
+ * @private
4834
+ */
4835
+ const EVT_PROPS_CONFIG = { writable: false, value: this };
4836
+ /**
4837
+ * @private
4838
+ * A utility class used as delegate of `XMLHttpRequest` functionalities when
4839
+ * a HTTP request is intercepted by the Mocking Framework .
4840
+ */
4841
+ class DelegateXhr extends XhrBase {
4842
+ /**
4843
+ * Returns the response body content.
4844
+ *
4845
+ * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/response
4846
+ */
4847
+ get response() {
4848
+ return this._dataStorage?.data || null;
4849
+ }
4850
+ /**
4851
+ * Returns the numerical HTTP status code of the `XMLHttpRequest` response.
4852
+ *
4853
+ * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/status
4854
+ */
4855
+ get status() {
4856
+ return this._status;
4857
+ }
4858
+ /**
4859
+ * Returns a string containing the response status message as returned by the HTTP server.
4860
+ *
4861
+ * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/statusText
4862
+ */
4863
+ get statusText() {
4864
+ return this._statusText;
4865
+ }
4866
+ /**
4867
+ * Returns the state the `XMLHttpRequest` client is in.
4868
+ *
4869
+ * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/readyState
4870
+ */
4871
+ get readyState() {
4872
+ return this._readyState;
4873
+ }
4874
+ /**
4875
+ * Returns the serialized URL of the response or the empty string if the URL is `null`.
4876
+ *
4877
+ * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/responseURL
4878
+ */
4879
+ get responseURL() {
4880
+ return this._url;
4881
+ }
4882
+ /**
4883
+ * Returns the text received from a server following a request being sent.
4884
+ *
4885
+ * Throws an `InvalidStateError` DOMException if responseType is not the empty string or "text".
4886
+ *
4887
+ * @see https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/responseText
4888
+ */
4889
+ get responseText() {
4890
+ return this._dataStorage?.stringifiedData || EMPTY_STRING;
4891
+ }
4892
+ /**
4893
+ * Returns an `XMLHttpRequestUpload` object that can be observed to monitor an upload progress.
4894
+ *
4895
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/upload
4896
+ */
4897
+ get upload() {
4898
+ return null;
4899
+ }
4900
+ /**
4901
+ * @private
4902
+ */
4903
+ open(method, url, async, username, password) {
4904
+ this._method = method;
4905
+ this._url = url;
4906
+ this.setReadyState(this.OPENED);
4907
+ }
4908
+ /**
4909
+ * Aborts the request if it has already been sent. When a request is aborted, its `readyState`
4910
+ * is changed to `XMLHttpRequest.UNSENT` and the request status code is set to `0`.
4911
+ */
4912
+ abort() {
4913
+ this._readyState = this.UNSENT;
4914
+ this._status = 0;
4915
+ this.eventDispatch("abort");
4916
+ }
4917
+ /**
4918
+ * Returns all the response headers, separated by CRLF, as a string, or returns `null`
4919
+ * if no response has been received.
4920
+ *
4921
+ * @returns All the response headers, separated by CRLF, as a string, or returns `null`
4922
+ * if no response has been received.
4923
+ */
4924
+ getAllResponseHeaders() {
4925
+ if (this._readyState < this.HEADERS_RECEIVED)
4926
+ return null;
4927
+ const respHeaders = this._dataStorage?.httpResponse.headers;
4928
+ if (respHeaders)
4929
+ return HttpHeadersUtil.stringify(respHeaders);
4930
+ return null;
4931
+ }
4932
+ /**
4933
+ * Sends the request to the server.
4934
+ *
4935
+ * @param body A body of data to be sent in the XHR request.
4936
+ */
4937
+ send(body) {
4938
+ const start = this.now();
4939
+ const request = this.buildHttpRequest(body);
3965
4940
  const rc = this._routeConfig;
3966
4941
  const httpResponseMock = rc.methodConfig.data(request, rc.parameters);
3967
- let timer = httpResponseMock.delay || 0;
3968
- if (timer > MAX_TIMER)
3969
- timer = MAX_TIMER;
4942
+ const responseDelay = HttpMockResponseDelayUtil.getResponseDelay(httpResponseMock.delay || 0);
4943
+ const timer = responseDelay.duration;
4944
+ const requestMetadata = {
4945
+ start: start,
4946
+ stalled: responseDelay.stalled,
4947
+ duration: timer,
4948
+ url: new URL(this._url),
4949
+ id: Uuid.build()
4950
+ };
4951
+ const prefetchMetadata = {
4952
+ request: request,
4953
+ requestMetadata: requestMetadata
4954
+ };
4955
+ this._logger.prefetch(prefetchMetadata);
3970
4956
  this._loadSubscription = this.loadData(httpResponseMock).subscribe({
3971
4957
  next: (data) => {
3972
- this.setDataStorage(httpResponseMock, data);
4958
+ this.setDataStorage(httpResponseMock, requestMetadata, data);
3973
4959
  const error = this._dataStorage.httpResponse.error;
3974
4960
  setTimeout(() => {
3975
4961
  this.setReadyState(this.HEADERS_RECEIVED);
3976
4962
  if (error)
3977
- return this.onError(error);
4963
+ return this.onError(request, error);
3978
4964
  this.setReadyState(this.LOADING);
3979
4965
  const response = this._dataStorage.httpResponse;
3980
- let headers = response.headers;
3981
- if (headers) {
3982
- this._headers.keys().forEach((key) => {
3983
- headers = headers.set(key, this._headers.get(key));
3984
- });
3985
- this._headers = headers;
3986
- }
3987
4966
  if (!this._progressiveDownload) {
3988
4967
  this._statusText = response.statusText || EMPTY_STRING;
3989
4968
  this._status = response.status || 0;
3990
- return this.onLoadComplete();
4969
+ return this.onLoadComplete(request);
3991
4970
  }
3992
- this.doProgressiveDownload();
4971
+ this.doProgressiveDownload(request);
3993
4972
  }, timer);
3994
4973
  },
3995
4974
  error: (err) => {
3996
- this.setDataStorage(httpResponseMock);
3997
- this.onError(err);
4975
+ this.setDataStorage(httpResponseMock, requestMetadata);
4976
+ this.onError(request, err);
4977
+ }
4978
+ });
4979
+ }
4980
+ /**
4981
+ * Sets the value of an HTTP request header.
4982
+ *
4983
+ * @param name The name of the header whose value is to be set.
4984
+ * @param value The value to set as the body of the header.
4985
+ */
4986
+ setRequestHeader(name, value) {
4987
+ this._requestHeaders = this._requestHeaders.set(name, value);
4988
+ }
4989
+ /**
4990
+ * @private
4991
+ */
4992
+ constructor(routeConfig, _logger) {
4993
+ super();
4994
+ this._logger = _logger;
4995
+ /**
4996
+ * @private
4997
+ * Indicates whether the progressive download is activated, or not.
4998
+ */
4999
+ this._progressiveDownload = false;
5000
+ /**
5001
+ * @private
5002
+ *
5003
+ * Internal storage for HTTP response `data`.
5004
+ */
5005
+ this._dataStorage = null;
5006
+ /**
5007
+ * @private
5008
+ *
5009
+ * Internal storage for the HTTP request `readyState`.
5010
+ */
5011
+ this._readyState = this.UNSENT;
5012
+ /**
5013
+ * @private
5014
+ *
5015
+ * Internal storage for the HTTP request `headers`.
5016
+ */
5017
+ this._requestHeaders = null;
5018
+ /**
5019
+ * @private
5020
+ *
5021
+ * Internal storage for the HTTP request `status`.
5022
+ */
5023
+ this._status = 0;
5024
+ /**
5025
+ * @private
5026
+ *
5027
+ * Internal storage for the HTTP request `statusText`.
5028
+ */
5029
+ this._statusText = EMPTY_STRING;
5030
+ /**
5031
+ * @private
5032
+ */
5033
+ this._loadSubscription = null;
5034
+ /**
5035
+ * Returns an an enumerated string value specifying the type of data contained in the response.
5036
+ *
5037
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType
5038
+ */
5039
+ this.responseType = EMPTY_STRING;
5040
+ this._routeConfig = routeConfig;
5041
+ // routeConfig.methodConfig.downloadManager
5042
+ this._progressiveDownload = false;
5043
+ this._requestHeaders = new HttpHeaders();
5044
+ }
5045
+ /**
5046
+ * @private
5047
+ * Internally used by the framework to delete a `DelegateXhr` instance.
5048
+ */
5049
+ destroy() {
5050
+ this._routeConfig = null;
5051
+ this._requestHeaders = null;
5052
+ this._dataStorage = null;
5053
+ if (this._loadSubscription) {
5054
+ this._loadSubscription.unsubscribe();
5055
+ this._loadSubscription = null;
5056
+ }
5057
+ }
5058
+ /**
5059
+ * @private
5060
+ */
5061
+ doProgressiveDownload(request) {
5062
+ const total = this._dataStorage.total;
5063
+ if (total <= 200) {
5064
+ console.warn("[Angular Toolbox]: Body content is too small for emulating progressive download! Minimum size is 200 octets.");
5065
+ return this.onLoadComplete(request);
5066
+ }
5067
+ // TODO: ameliorate the following process:
5068
+ const self = this;
5069
+ const chunckSize = Math.floor(total / 10);
5070
+ let cursor = 0;
5071
+ this._statusText = "Partial Content";
5072
+ this._status = HttpStatusCode.PartialContent;
5073
+ const idx = setInterval(() => {
5074
+ cursor += chunckSize;
5075
+ if (cursor > total) {
5076
+ cursor = total;
5077
+ clearInterval(idx);
5078
+ self.onLoadComplete(request);
3998
5079
  }
3999
- });
5080
+ else {
5081
+ this._dataStorage.loaded = cursor;
5082
+ self.dispatchProgressEvent();
5083
+ }
5084
+ }, 100);
5085
+ }
5086
+ finalizeRequestMetadata() {
5087
+ const ds = this._dataStorage;
5088
+ const metadata = ds.requestMetadata;
5089
+ const duration = this.now() - metadata.start;
5090
+ if (duration > metadata.duration)
5091
+ metadata.duration = duration;
5092
+ return metadata;
5093
+ }
5094
+ /**
5095
+ * @private
5096
+ */
5097
+ onLoadComplete(request) {
5098
+ this._dataStorage.loaded = this._dataStorage.total;
5099
+ this.setReadyState(this.DONE);
5100
+ this.dispatchProgressEvent("load");
5101
+ this._logger.info(this.buildMetadata(request));
5102
+ }
5103
+ /**
5104
+ * @private
5105
+ */
5106
+ onError(request, error) {
5107
+ this._status = error.status;
5108
+ this._statusText = error.statusText;
5109
+ this.setReadyState(this.DONE);
5110
+ this.dispatchProgressEvent("error");
5111
+ this._logger.error(this.buildMetadata(request));
5112
+ }
5113
+ /**
5114
+ * @private
5115
+ */
5116
+ buildMetadata(request) {
5117
+ return HttpMockLoggingMetadataBuilder.build(this, request, this.finalizeRequestMetadata());
5118
+ }
5119
+ /**
5120
+ * @private
5121
+ */
5122
+ eventDispatch(type) {
5123
+ const event = new Event(type);
5124
+ Object.defineProperty(event, 'target', EVT_PROPS_CONFIG);
5125
+ Object.defineProperty(event, 'currentTarget', EVT_PROPS_CONFIG);
5126
+ this.dispatchEvent(event);
5127
+ }
5128
+ /**
5129
+ * @private
5130
+ */
5131
+ dispatchProgressEvent(type = "progress") {
5132
+ const d = this._dataStorage;
5133
+ const event = new ProgressEventMock(type);
5134
+ event.loaded = d.loaded;
5135
+ event.total = d.total;
5136
+ this.dispatchEvent(event);
5137
+ }
5138
+ /**
5139
+ * @private
5140
+ */
5141
+ setReadyState(state) {
5142
+ this._readyState = state;
5143
+ const event = this.onreadystatechange;
5144
+ if (event)
5145
+ event.call(this, READY_STATE_CHANGE_EVENT);
5146
+ }
5147
+ /**
5148
+ * @private
5149
+ */
5150
+ loadData(httpResponseMock) {
5151
+ const responseBody = httpResponseMock.body;
5152
+ return (responseBody instanceof Observable) ? responseBody : of(responseBody);
5153
+ }
5154
+ /**
5155
+ * @private
5156
+ */
5157
+ setDataStorage(responseMock, requestMetadata, data = null) {
5158
+ this._dataStorage = DataStorageBuilder.buildDataStorage(responseMock, data, requestMetadata);
5159
+ }
5160
+ /**
5161
+ * @private
5162
+ */
5163
+ buildHttpRequest(body) {
5164
+ let params = new HttpParams();
5165
+ const it = this._routeConfig.searchParams.entries();
5166
+ for (const pair of it)
5167
+ params = params.set(pair[0], pair[1]);
5168
+ const init = {
5169
+ params: params,
5170
+ headers: this._requestHeaders,
5171
+ withCredentials: this.withCredentials,
5172
+ responseType: this.responseType,
5173
+ reportProgress: this.hasEventListener("progress")
5174
+ // context, transferCache: not used by Angular at this level of API
5175
+ };
5176
+ return new HttpRequest(this._method, this._url, body, init);
5177
+ }
5178
+ now() {
5179
+ return Date.now();
5180
+ }
5181
+ }
5182
+
5183
+ /**
5184
+ * @license
5185
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5186
+ *
5187
+ * Use of this source code is governed by an MIT-style license that can be found in
5188
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5189
+ */
5190
+ /**
5191
+ * @private
5192
+ * An error used as reference for unit testing.
5193
+ * Angular framework calls `XMLHttpRequest` method only after the `open()` method invokation.
5194
+ */
5195
+ const XHR_ERROR = (method) => {
5196
+ throw new Error(`Attempt to call ${method}() method before calling open().`);
5197
+ };
5198
+ /**
5199
+ * @private
5200
+ * A XHR proxy that is used by the Mocking Framework to apply HTTP call strategies.
5201
+ */
5202
+ class XhrProxyImpl extends XhrBase {
5203
+ /**
5204
+ * @private
5205
+ *
5206
+ * XMLHTTPRequest API
5207
+ */
5208
+ get response() {
5209
+ return this.XHR ? this.XHR.response : undefined;
5210
+ }
5211
+ /**
5212
+ * @private
5213
+ *
5214
+ * XMLHTTPRequest API
5215
+ */
5216
+ get status() {
5217
+ return this.XHR ? this.XHR.status : 0;
5218
+ }
5219
+ /**
5220
+ * @private
5221
+ *
5222
+ * XMLHTTPRequest API
5223
+ */
5224
+ get statusText() {
5225
+ return this.XHR ? this.XHR.statusText : EMPTY_STRING;
5226
+ }
5227
+ /**
5228
+ * @private
5229
+ *
5230
+ * XMLHTTPRequest API
5231
+ */
5232
+ get readyState() {
5233
+ return this.XHR ? this.XHR.readyState : this.UNSENT;
5234
+ }
5235
+ /**
5236
+ * @private
5237
+ *
5238
+ * XMLHTTPRequest API
5239
+ */
5240
+ get responseURL() {
5241
+ return this.XHR ? this.XHR.responseURL : EMPTY_STRING;
5242
+ }
5243
+ /**
5244
+ * @private
5245
+ *
5246
+ * XMLHTTPRequest API
5247
+ */
5248
+ get responseText() {
5249
+ return this.XHR ? this.XHR.responseText : EMPTY_STRING;
5250
+ }
5251
+ /**
5252
+ * @private
5253
+ *
5254
+ * XMLHTTPRequest API
5255
+ */
5256
+ get responseType() {
5257
+ return this.XHR ? this.XHR.responseType : EMPTY_STRING;
5258
+ }
5259
+ /**
5260
+ * @private
5261
+ *
5262
+ * XMLHTTPRequest API
5263
+ */
5264
+ set responseType(value) {
5265
+ if (!this.XHR)
5266
+ XHR_ERROR("responseType");
5267
+ this.XHR.responseType = value;
5268
+ }
5269
+ get upload() {
5270
+ return this.XHR.upload;
5271
+ }
5272
+ open(method, url, async, username, password) {
5273
+ const m = method.toString().toLowerCase();
5274
+ const parsedUrl = URL.canParse(url) ? new URL(url) : new URL(this._httpMockService.getAppOrigin() + url);
5275
+ const config = this._httpMockService.getRouteConfig(parsedUrl, m);
5276
+ if (this.XHR && this.XHR instanceof DelegateXhr)
5277
+ this.XHR.destroy();
5278
+ this.XHR = config ? new DelegateXhr(config, this._logger) : new XMLHttpRequest();
5279
+ this.XHR.withCredentials = this.withCredentials;
5280
+ this.XHR.open(m.toString(), parsedUrl.toString());
5281
+ }
5282
+ /**
5283
+ * @private
5284
+ *
5285
+ * XMLHTTPRequest API
5286
+ */
5287
+ abort() {
5288
+ if (this.XHR)
5289
+ return this.XHR.abort();
5290
+ XHR_ERROR("abort");
5291
+ }
5292
+ /**
5293
+ * @private
5294
+ *
5295
+ * XMLHTTPRequest API
5296
+ */
5297
+ getAllResponseHeaders() {
5298
+ return this.XHR ? this.XHR.getAllResponseHeaders() : null;
5299
+ }
5300
+ /**
5301
+ * @private
5302
+ *
5303
+ * XMLHTTPRequest API
5304
+ */
5305
+ addEventListener(type, listener, options) {
5306
+ if (this.XHR)
5307
+ return this.XHR.addEventListener(type, listener, options);
5308
+ XHR_ERROR("addEventListener");
5309
+ }
5310
+ /**
5311
+ * @private
5312
+ *
5313
+ * XMLHTTPRequest API
5314
+ */
5315
+ removeEventListener(type, listener, options) {
5316
+ if (this.XHR)
5317
+ return this.XHR.removeEventListener(type, listener, options);
5318
+ XHR_ERROR("removeEventListener");
4000
5319
  }
4001
5320
  /**
4002
- * Sets the value of an HTTP request header.
5321
+ * @private
4003
5322
  *
4004
- * @param name The name of the header whose value is to be set.
4005
- * @param value The value to set as the body of the header.
5323
+ * XMLHTTPRequest API
5324
+ */
5325
+ send(body) {
5326
+ if (this.XHR)
5327
+ return this.XHR.send(body);
5328
+ XHR_ERROR("send");
5329
+ }
5330
+ /**
5331
+ * @private
5332
+ *
5333
+ * XMLHTTPRequest API
4006
5334
  */
4007
5335
  setRequestHeader(name, value) {
4008
- this._headers = this._headers.set(name, value);
5336
+ if (this.XHR)
5337
+ return this.XHR.setRequestHeader(name, value);
5338
+ XHR_ERROR("setRequestHeader");
5339
+ }
5340
+ /**
5341
+ * @private
5342
+ *
5343
+ * For Unit Testing only.
5344
+ */
5345
+ instanceOf(classRef) {
5346
+ return this.XHR instanceof classRef;
4009
5347
  }
4010
5348
  /**
4011
5349
  * @private
4012
5350
  */
4013
- constructor(routeConfig) {
5351
+ constructor(_httpMockService, _logger) {
4014
5352
  super();
5353
+ this._httpMockService = _httpMockService;
5354
+ this._logger = _logger;
5355
+ }
5356
+ }
5357
+
5358
+ /**
5359
+ * @license
5360
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5361
+ *
5362
+ * Use of this source code is governed by an MIT-style license that can be found in
5363
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5364
+ */
5365
+ /**
5366
+ * @private
5367
+ * The concrete implementation of the `XhrFactory` interface.
5368
+ */
5369
+ class XhrProxyFactoryImpl extends XhrFactory {
5370
+ /**
5371
+ * @private
5372
+ */
5373
+ constructor(_httpMockService, _logger) {
5374
+ super();
5375
+ this._httpMockService = _httpMockService;
5376
+ this._logger = _logger;
5377
+ }
5378
+ /**
5379
+ * @private
5380
+ */
5381
+ build() {
5382
+ return new XhrProxyImpl(this._httpMockService, this._logger);
5383
+ }
5384
+ }
5385
+
5386
+ /**
5387
+ * @license
5388
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5389
+ *
5390
+ * Use of this source code is governed by an MIT-style license that can be found in
5391
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5392
+ */
5393
+ /**
5394
+ * A factory function that creates and returns a new `XhrFactory` object.
5395
+ *
5396
+ * @returns A new `XhrFactory` object.
5397
+ */
5398
+ const httpMockFactory = () => {
5399
+ return new XhrProxyFactoryImpl(inject(HttpMockService), inject(HttpMockLoggingService$1));
5400
+ };
5401
+
5402
+ /**
5403
+ * @license
5404
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5405
+ *
5406
+ * Use of this source code is governed by an MIT-style license that can be found in
5407
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5408
+ */
5409
+ /**
5410
+ * An implementation of the `LogConnector` class that sends logs to the HTTP
5411
+ * mocking console component.
5412
+ */
5413
+ class HttpMonitoringConsoleLogConnector {
5414
+ constructor() {
4015
5415
  /**
4016
- * @private
4017
- * Indicates whether the progressive download is activated, or not.
4018
- */
4019
- this._progressiveDownload = false;
4020
- /**
4021
- * @private
4022
- *
4023
- * Internal storage for HTTP response `data`.
4024
- */
4025
- this._dataStorage = null;
4026
- /**
4027
- * @private
4028
- *
4029
- * Internal storage for the HTTP request `readyState`.
4030
- */
4031
- this._readyState = this.UNSENT;
4032
- /**
4033
- * @private
4034
- *
4035
- * Internal storage for the HTTP request `headers`.
4036
- */
4037
- this._headers = null;
4038
- /**
4039
- * @private
4040
- *
4041
- * Internal storage for the HTTP request `status`.
4042
- */
4043
- this._status = 0;
4044
- /**
4045
- * @private
4046
- *
4047
- * Internal storage for the HTTP request `statusText`.
4048
- */
4049
- this._statusText = EMPTY_STRING;
4050
- /**
4051
- * @private
4052
- */
4053
- this._loadSubscription = null;
4054
- /**
4055
- * Returns an an enumerated string value specifying the type of data contained in the response.
4056
5416
  *
4057
- * @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType
4058
5417
  */
4059
- this.responseType = "";
4060
- const methodConfig = routeConfig.methodConfig;
4061
- this._routeConfig = routeConfig;
4062
- this._progressiveDownload = methodConfig.progressive || false;
4063
- this.responseType = methodConfig.responseType || EMPTY_STRING;
4064
- this._headers = new HttpHeaders();
5418
+ this.logs = [];
5419
+ this.change = new EventEmitter(true);
4065
5420
  }
4066
5421
  /**
4067
- * @private
4068
- * Internally used by the framework to delete a `DelegateXhr` instance.
5422
+ * @inheritdoc
4069
5423
  */
4070
- destroy() {
4071
- this._routeConfig = null;
4072
- this._headers = null;
4073
- this._dataStorage = null;
4074
- if (this._loadSubscription) {
4075
- this._loadSubscription.unsubscribe();
4076
- this._loadSubscription = null;
4077
- }
5424
+ destroy() { }
5425
+ /**
5426
+ * @inheritdoc
5427
+ */
5428
+ init(logList) {
5429
+ this.logs.push(...logList);
4078
5430
  }
4079
5431
  /**
4080
- * @private
5432
+ * @inheritdoc
4081
5433
  */
4082
- doProgressiveDownload() {
4083
- const total = this._dataStorage.total;
4084
- if (total <= 200) {
4085
- console.warn("[Angular Toolbox]: Body content is too small for emulating progressive download! Minimum size is 200 octets.");
4086
- return this.onLoadComplete();
5434
+ sendLog(log) {
5435
+ const level = log.level;
5436
+ if (level === LogLevel.INFO || LogLevel.ERROR)
5437
+ this.logs.push(log);
5438
+ this.change.emit(log);
5439
+ }
5440
+ /**
5441
+ * @inheritdoc
5442
+ */
5443
+ clearLogs() {
5444
+ this.logs.length = 0;
5445
+ }
5446
+ /**
5447
+ * Not supported.
5448
+ */
5449
+ copyLogs() { }
5450
+ }
5451
+
5452
+ /**
5453
+ * @license
5454
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5455
+ *
5456
+ * Use of this source code is governed by an MIT-style license that can be found in
5457
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5458
+ */
5459
+ class AtxJsonViewerPanelComponent {
5460
+ constructor() {
5461
+ this.data = null;
5462
+ }
5463
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxJsonViewerPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5464
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.3", type: AtxJsonViewerPanelComponent, isStandalone: true, selector: "atx-json-viewer-panel", inputs: { data: "data" }, ngImport: i0, template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n@if (data) {\r\n @if (data.children) {\r\n <details>\r\n <summary>\r\n @if (data.label) {\r\n <span class=\"atx-prop-label\">{{ data.label }}</span>:\r\n <span [ngClass]=\"data.typeClass\">{{ data.value }}</span>\r\n } @else {\r\n {{ data.value }}\r\n }\r\n </summary>\r\n @for (item of data.children; track item) {\r\n <atx-json-viewer-panel [data]=\"item\"/>\r\n }\r\n </details>\r\n } @else {\r\n <div class=\"primitive\">\r\n <span class=\"atx-prop-label\">{{ data.label }}</span>: <span [ngClass]=\"data.typeClass\">{{ data.value }}</span>\r\n </div>\r\n }\r\n}\r\n", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}:host{display:block;font-family:monospace;font-size:13px}summary:hover{background-color:var(--dark-gray)}summary{padding-left:6px}atx-json-viewer-panel{padding-left:26px}.primitive{margin-left:20px}.atx-prop-label{font-weight:700;color:#8a2be2}.atx-string{color:#cd5c5c}.atx-string:before,.atx-string:after{content:'\"'}.atx-boolean,.atx-null,.atx-number{color:#0000cd}.atx-boolean,.atx-null{font-weight:700}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"], dependencies: [{ kind: "component", type: AtxJsonViewerPanelComponent, selector: "atx-json-viewer-panel", inputs: ["data"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
5465
+ }
5466
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxJsonViewerPanelComponent, decorators: [{
5467
+ type: Component,
5468
+ args: [{ selector: 'atx-json-viewer-panel', standalone: true, imports: [
5469
+ CommonModule
5470
+ ], template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n@if (data) {\r\n @if (data.children) {\r\n <details>\r\n <summary>\r\n @if (data.label) {\r\n <span class=\"atx-prop-label\">{{ data.label }}</span>:\r\n <span [ngClass]=\"data.typeClass\">{{ data.value }}</span>\r\n } @else {\r\n {{ data.value }}\r\n }\r\n </summary>\r\n @for (item of data.children; track item) {\r\n <atx-json-viewer-panel [data]=\"item\"/>\r\n }\r\n </details>\r\n } @else {\r\n <div class=\"primitive\">\r\n <span class=\"atx-prop-label\">{{ data.label }}</span>: <span [ngClass]=\"data.typeClass\">{{ data.value }}</span>\r\n </div>\r\n }\r\n}\r\n", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}:host{display:block;font-family:monospace;font-size:13px}summary:hover{background-color:var(--dark-gray)}summary{padding-left:6px}atx-json-viewer-panel{padding-left:26px}.primitive{margin-left:20px}.atx-prop-label{font-weight:700;color:#8a2be2}.atx-string{color:#cd5c5c}.atx-string:before,.atx-string:after{content:'\"'}.atx-boolean,.atx-null,.atx-number{color:#0000cd}.atx-boolean,.atx-null{font-weight:700}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }]
5471
+ }], propDecorators: { data: [{
5472
+ type: Input
5473
+ }] } });
5474
+
5475
+ /**
5476
+ * @license
5477
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5478
+ *
5479
+ * Use of this source code is governed by an MIT-style license that can be found in
5480
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5481
+ */
5482
+ var ConsoleBodyType;
5483
+ (function (ConsoleBodyType) {
5484
+ ConsoleBodyType[ConsoleBodyType["INVALID"] = -1] = "INVALID";
5485
+ ConsoleBodyType[ConsoleBodyType["NULL"] = 0] = "NULL";
5486
+ ConsoleBodyType[ConsoleBodyType["JSON"] = 1] = "JSON";
5487
+ ConsoleBodyType[ConsoleBodyType["TEXT"] = 2] = "TEXT";
5488
+ ConsoleBodyType[ConsoleBodyType["BLOB"] = 3] = "BLOB";
5489
+ ConsoleBodyType[ConsoleBodyType["FORM_DATA"] = 4] = "FORM_DATA";
5490
+ ConsoleBodyType[ConsoleBodyType["ARRAY_BUFFER"] = 5] = "ARRAY_BUFFER";
5491
+ })(ConsoleBodyType || (ConsoleBodyType = {}));
5492
+
5493
+ /**
5494
+ * @license
5495
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5496
+ *
5497
+ * Use of this source code is governed by an MIT-style license that can be found in
5498
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5499
+ */
5500
+ var ConsoleTypeClass;
5501
+ (function (ConsoleTypeClass) {
5502
+ ConsoleTypeClass["OBJECT"] = "atx-object";
5503
+ ConsoleTypeClass["STRING"] = "atx-string";
5504
+ ConsoleTypeClass["NUMBER"] = "atx-number";
5505
+ ConsoleTypeClass["BOOLEAN"] = "atx-boolean";
5506
+ ConsoleTypeClass["ARRAY"] = "atx-array";
5507
+ ConsoleTypeClass["NULL"] = "atx-null";
5508
+ })(ConsoleTypeClass || (ConsoleTypeClass = {}));
5509
+
5510
+ /**
5511
+ * @license
5512
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5513
+ *
5514
+ * Use of this source code is governed by an MIT-style license that can be found in
5515
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5516
+ */
5517
+ const NULL = "null";
5518
+ const ARR_END = '...]';
5519
+ const OBJ_END = '...}';
5520
+ class DataUtil {
5521
+ static parseJson(obj, label) {
5522
+ const primitive = typeof obj;
5523
+ let type = ConsoleTypeClass.OBJECT, value = obj, children = null;
5524
+ if (primitive === STRING)
5525
+ type = ConsoleTypeClass.STRING;
5526
+ else if (primitive === NUMBER)
5527
+ type = ConsoleTypeClass.NUMBER;
5528
+ else if (primitive === BOOLEAN)
5529
+ type = ConsoleTypeClass.BOOLEAN;
5530
+ else if (Array.isArray(obj)) {
5531
+ const rawValue = JSON.stringify(obj);
5532
+ let len = obj.length - 1;
5533
+ let idx = 0;
5534
+ type = ConsoleTypeClass.ARRAY;
5535
+ value = rawValue.length > 50 ? rawValue.substring(0, 46) + ARR_END : rawValue;
5536
+ children = [];
5537
+ for (; len >= 0; len--) {
5538
+ children.push(DataUtil.parseJson(obj[len], String(idx)));
5539
+ idx++;
5540
+ }
4087
5541
  }
4088
- // TODO: ameliorate the following process:
4089
- const self = this;
4090
- const chunckSize = Math.floor(total / 10);
4091
- let cursor = 0;
4092
- this._statusText = "Partial Content";
4093
- this._status = HttpStatusCode.PartialContent;
4094
- const idx = setInterval(() => {
4095
- cursor += chunckSize;
4096
- if (cursor > total) {
4097
- cursor = total;
4098
- clearInterval(idx);
4099
- self.onLoadComplete();
5542
+ else if (obj === null) {
5543
+ type = ConsoleTypeClass.NULL;
5544
+ value = NULL;
5545
+ }
5546
+ else {
5547
+ const keys = Object.keys(obj);
5548
+ const rawValue = JSON.stringify(obj);
5549
+ let len = keys.length - 1;
5550
+ children = [];
5551
+ for (; len >= 0; len--) {
5552
+ const key = keys[len];
5553
+ children.push(DataUtil.parseJson(obj[key], key));
4100
5554
  }
4101
- else {
4102
- this._dataStorage.loaded = cursor;
4103
- self.dispatchProgressEvent();
5555
+ value = rawValue.length > 50 ? rawValue.substring(0, 46) + OBJ_END : rawValue;
5556
+ }
5557
+ return {
5558
+ label: label,
5559
+ typeClass: type,
5560
+ value: value,
5561
+ children: children
5562
+ };
5563
+ }
5564
+ static getBodyType(obj) {
5565
+ const primitive = typeof obj;
5566
+ if (obj === null || obj === undefined)
5567
+ return ConsoleBodyType.NULL;
5568
+ if (primitive === STRING)
5569
+ return ConsoleBodyType.TEXT;
5570
+ if (obj instanceof Blob)
5571
+ return ConsoleBodyType.BLOB;
5572
+ if (obj instanceof FormData)
5573
+ return ConsoleBodyType.FORM_DATA;
5574
+ if (obj instanceof ArrayBuffer)
5575
+ return ConsoleBodyType.ARRAY_BUFFER;
5576
+ if (primitive === OBJECT)
5577
+ return ConsoleBodyType.JSON;
5578
+ return ConsoleBodyType.INVALID;
5579
+ }
5580
+ }
5581
+
5582
+ /**
5583
+ * @license
5584
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5585
+ *
5586
+ * Use of this source code is governed by an MIT-style license that can be found in
5587
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5588
+ */
5589
+ class AtxJsonViewerComponent {
5590
+ constructor() {
5591
+ this.parsedData = null;
5592
+ }
5593
+ set data(value) {
5594
+ if (!value) {
5595
+ this.parsedData = null;
5596
+ return;
5597
+ }
5598
+ this.parsedData = DataUtil.parseJson(value);
5599
+ }
5600
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxJsonViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5601
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.0.3", type: AtxJsonViewerComponent, isStandalone: true, selector: "atx-json-viewer", inputs: { data: "data" }, ngImport: i0, template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n<atx-json-viewer-panel [data]=\"parsedData\"/>", styles: ["/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"], dependencies: [{ kind: "component", type: AtxJsonViewerPanelComponent, selector: "atx-json-viewer-panel", inputs: ["data"] }] }); }
5602
+ }
5603
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxJsonViewerComponent, decorators: [{
5604
+ type: Component,
5605
+ args: [{ selector: 'atx-json-viewer', standalone: true, imports: [
5606
+ AtxJsonViewerPanelComponent
5607
+ ], template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n<atx-json-viewer-panel [data]=\"parsedData\"/>", styles: ["/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }]
5608
+ }], propDecorators: { data: [{
5609
+ type: Input
5610
+ }] } });
5611
+
5612
+ /**
5613
+ * @license
5614
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5615
+ *
5616
+ * Use of this source code is governed by an MIT-style license that can be found in
5617
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5618
+ */
5619
+ class AtxPayloadRendererComponent {
5620
+ set log(value) {
5621
+ const request = value?.metadata.request;
5622
+ const params = request.params;
5623
+ const paramsKeys = params.keys();
5624
+ const body = request.body;
5625
+ const bodyType = DataUtil.getBodyType(body);
5626
+ this.queryParams = this.formData = this.json = null;
5627
+ if (paramsKeys.length > 0) {
5628
+ this.queryParams = [];
5629
+ paramsKeys.forEach(key => this.queryParams?.push({ key: key, value: params.get(key) }));
5630
+ }
5631
+ if (bodyType === ConsoleBodyType.FORM_DATA) {
5632
+ this.formData = Array.from(body);
5633
+ }
5634
+ else if (bodyType === ConsoleBodyType.TEXT) {
5635
+ this.json = JSON.parse(body);
5636
+ }
5637
+ this._cdr.detectChanges();
5638
+ }
5639
+ constructor(_cdr) {
5640
+ this._cdr = _cdr;
5641
+ this.json = null;
5642
+ this.formData = null;
5643
+ this.queryParams = null;
5644
+ }
5645
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxPayloadRendererComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
5646
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.3", type: AtxPayloadRendererComponent, isStandalone: true, selector: "atx-payload-renderer", inputs: { log: "log" }, ngImport: i0, template: "\r\n<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n@if (queryParams) {\r\n <details>\r\n <summary>\r\n Query String Parameters\r\n </summary>\r\n <div class=\"content\">\r\n @for (item of queryParams; track item) {\r\n <dl>\r\n <dt>{{ item.key }}:</dt>\r\n <dd>{{ item.value }}</dd>\r\n </dl>\r\n }\r\n </div>\r\n </details>\r\n}\r\n@if (json) {\r\n <details>\r\n <summary>\r\n Request Payload\r\n </summary>\r\n <div class=\"content\">\r\n <atx-json-viewer [data]=\"json\"/>\r\n </div>\r\n </details>\r\n} @else if (formData) {\r\n <details>\r\n <summary>\r\n Form Data\r\n </summary>\r\n <div class=\"content\">\r\n <ul>\r\n @for (entry of formData; track entry) {\r\n <li>[ {{ entry }} ]</li>\r\n }\r\n </ul>\r\n </div>\r\n </details>\r\n} \r\n", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}details{border:1px solid var(--border-color)}summary{font-weight:700;padding:4px 6px}summary:hover{background-color:var(--dark-gray)}dl{display:flex;gap:6px;margin:0 0 0 20px}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"], dependencies: [{ kind: "component", type: AtxJsonViewerComponent, selector: "atx-json-viewer", inputs: ["data"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5647
+ }
5648
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxPayloadRendererComponent, decorators: [{
5649
+ type: Component,
5650
+ args: [{ selector: 'atx-payload-renderer', standalone: true, imports: [
5651
+ AtxJsonViewerComponent
5652
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "\r\n<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n@if (queryParams) {\r\n <details>\r\n <summary>\r\n Query String Parameters\r\n </summary>\r\n <div class=\"content\">\r\n @for (item of queryParams; track item) {\r\n <dl>\r\n <dt>{{ item.key }}:</dt>\r\n <dd>{{ item.value }}</dd>\r\n </dl>\r\n }\r\n </div>\r\n </details>\r\n}\r\n@if (json) {\r\n <details>\r\n <summary>\r\n Request Payload\r\n </summary>\r\n <div class=\"content\">\r\n <atx-json-viewer [data]=\"json\"/>\r\n </div>\r\n </details>\r\n} @else if (formData) {\r\n <details>\r\n <summary>\r\n Form Data\r\n </summary>\r\n <div class=\"content\">\r\n <ul>\r\n @for (entry of formData; track entry) {\r\n <li>[ {{ entry }} ]</li>\r\n }\r\n </ul>\r\n </div>\r\n </details>\r\n} \r\n", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}details{border:1px solid var(--border-color)}summary{font-weight:700;padding:4px 6px}summary:hover{background-color:var(--dark-gray)}dl{display:flex;gap:6px;margin:0 0 0 20px}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }]
5653
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { log: [{
5654
+ type: Input
5655
+ }] } });
5656
+
5657
+ /**
5658
+ * @license
5659
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5660
+ *
5661
+ * Use of this source code is governed by an MIT-style license that can be found in
5662
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5663
+ */
5664
+ class AtxTimingRendererComponent {
5665
+ constructor() {
5666
+ this.hasData = false;
5667
+ this.start = NaN;
5668
+ this.downloadStart = NaN;
5669
+ this.downloadLength = NaN;
5670
+ this.duration = 0;
5671
+ this.error = false;
5672
+ }
5673
+ set data(value) {
5674
+ if (value) {
5675
+ const metadata = value.metadata;
5676
+ const requestMetadata = metadata.requestMetadata;
5677
+ const duration = requestMetadata.duration;
5678
+ const stalled = requestMetadata.stalled;
5679
+ this.error = metadata.response.status >= 400;
5680
+ this.hasData = true;
5681
+ this.start = requestMetadata.start;
5682
+ this.duration = duration;
5683
+ if (duration === 0) {
5684
+ this.downloadStart = this.downloadLength = 0;
5685
+ return;
4104
5686
  }
4105
- }, 100);
5687
+ const downloadLength = Math.round(100 * (duration - stalled) / duration);
5688
+ this.downloadStart = 100 - downloadLength;
5689
+ this.downloadLength = downloadLength;
5690
+ return;
5691
+ }
5692
+ this.hasData = this.error = false;
5693
+ this.start = this.downloadStart = this.downloadLength = NaN;
5694
+ this.duration = 0;
4106
5695
  }
5696
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxTimingRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5697
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.3", type: AtxTimingRendererComponent, isStandalone: true, selector: "atx-timing-renderer", inputs: { data: "data" }, ngImport: i0, template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n<section class=\"content\">\r\n@if (hasData) {\r\n <dl>\r\n <dt>Connection start</dt>\r\n <dd>{{ start | date: 'short' }}</dd>\r\n </dl>\r\n <dl>\r\n <dt>Request/Response</dt>\r\n <dd class=\"timeline\">\r\n <div>\r\n <div [attr.style]=\"'width:' + downloadStart + '%'\">\r\n stalled\r\n <div class=\"stalled\"></div>\r\n <div class=\"time\">{{ downloadStart }} ms</div>\r\n </div>\r\n <div [attr.style]=\"'width:' + downloadLength + '%;margin-left:' + downloadStart + '%'\">\r\n download\r\n <div class=\"download\" [class.error]=\"error\"></div>\r\n <div class=\"time\">{{ duration }} ms</div>\r\n </div>\r\n </div>\r\n </dd>\r\n </dl>\r\n} \r\n</section>\r\n", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}.timeline{width:100%;margin-top:6px}.download,.stalled{width:100%;height:10px}.stalled{background-color:var(--dark-gray)}.time{text-align:right;padding-right:4px}.download{background-color:#00bfff}.error{background-color:red}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"], dependencies: [{ kind: "pipe", type: DatePipe, name: "date" }] }); }
5698
+ }
5699
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxTimingRendererComponent, decorators: [{
5700
+ type: Component,
5701
+ args: [{ selector: 'atx-timing-renderer', standalone: true, imports: [
5702
+ DatePipe,
5703
+ NgStyle
5704
+ ], template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n<section class=\"content\">\r\n@if (hasData) {\r\n <dl>\r\n <dt>Connection start</dt>\r\n <dd>{{ start | date: 'short' }}</dd>\r\n </dl>\r\n <dl>\r\n <dt>Request/Response</dt>\r\n <dd class=\"timeline\">\r\n <div>\r\n <div [attr.style]=\"'width:' + downloadStart + '%'\">\r\n stalled\r\n <div class=\"stalled\"></div>\r\n <div class=\"time\">{{ downloadStart }} ms</div>\r\n </div>\r\n <div [attr.style]=\"'width:' + downloadLength + '%;margin-left:' + downloadStart + '%'\">\r\n download\r\n <div class=\"download\" [class.error]=\"error\"></div>\r\n <div class=\"time\">{{ duration }} ms</div>\r\n </div>\r\n </div>\r\n </dd>\r\n </dl>\r\n} \r\n</section>\r\n", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}.timeline{width:100%;margin-top:6px}.download,.stalled{width:100%;height:10px}.stalled{background-color:var(--dark-gray)}.time{text-align:right;padding-right:4px}.download{background-color:#00bfff}.error{background-color:red}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }]
5705
+ }], propDecorators: { data: [{
5706
+ type: Input
5707
+ }] } });
5708
+
5709
+ /**
5710
+ * A basic implementation of a HTML sanitization pipe.
5711
+ */
5712
+ class SafeHtmlPipe {
4107
5713
  /**
4108
5714
  * @private
4109
5715
  */
4110
- onLoadComplete() {
4111
- this._dataStorage.loaded = this._dataStorage.total;
4112
- this.setReadyState(this.DONE);
4113
- this.dispatchProgressEvent("load");
5716
+ constructor(_sanitizer) {
5717
+ this._sanitizer = _sanitizer;
4114
5718
  }
4115
5719
  /**
4116
- * @private
5720
+ * Transforms the HTML input string value into a `SafeHtml` instance and returns the result
5721
+ * of the transformation.
5722
+ *
5723
+ * @param value The HTML input value to transform into a `SafeHtml` instance.
5724
+ * @returns A `SafeHtml` instance based on the specified input value.
4117
5725
  */
4118
- onError(error) {
4119
- this._status = error.status;
4120
- this._statusText = error.statusText;
4121
- this.setReadyState(this.DONE);
4122
- this.dispatchProgressEvent("error");
5726
+ transform(value) {
5727
+ return this._sanitizer.bypassSecurityTrustHtml(value);
4123
5728
  }
4124
- /**
4125
- * @private
4126
- */
4127
- eventDispatch(type) {
4128
- const event = new Event(type);
4129
- Object.defineProperty(event, 'target', EVT_PROPS_CONFIG);
4130
- Object.defineProperty(event, 'currentTarget', EVT_PROPS_CONFIG);
4131
- this.dispatchEvent(event);
5729
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: SafeHtmlPipe, deps: [{ token: i1$2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe }); }
5730
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.0.3", ngImport: i0, type: SafeHtmlPipe, isStandalone: true, name: "safeHtml" }); }
5731
+ }
5732
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: SafeHtmlPipe, decorators: [{
5733
+ type: Pipe,
5734
+ args: [{
5735
+ name: 'safeHtml',
5736
+ standalone: true
5737
+ }]
5738
+ }], ctorParameters: () => [{ type: i1$2.DomSanitizer }] });
5739
+
5740
+ /**
5741
+ * @license
5742
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5743
+ *
5744
+ * Use of this source code is governed by an MIT-style license that can be found in
5745
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5746
+ */
5747
+ /**
5748
+ * @private
5749
+ */
5750
+ const SLASH = "/";
5751
+ class UrlUtil {
5752
+ static getResourceName(log) {
5753
+ return UrlUtil.getResourceNameFromPath(UrlUtil.getResourcePath(log));
4132
5754
  }
4133
- /**
4134
- * @private
4135
- */
4136
- dispatchProgressEvent(type = "progress") {
4137
- const d = this._dataStorage;
4138
- const event = new ProgressEventMock(type);
4139
- event.loaded = d.loaded;
4140
- event.total = d.total;
4141
- this.dispatchEvent(event);
5755
+ static getResourceNameFromPath(pathname) {
5756
+ const pos = pathname.length - 1;
5757
+ if (pathname.lastIndexOf(SLASH) === pos)
5758
+ pathname = pathname.substring(0, pos);
5759
+ return pathname.substring(pathname.lastIndexOf(SLASH) + 1);
4142
5760
  }
4143
- /**
4144
- * @private
4145
- */
4146
- setReadyState(state) {
4147
- this._readyState = state;
4148
- const event = this.onreadystatechange;
4149
- if (event)
4150
- event.call(this, READY_STATE_CHANGE_EVENT);
5761
+ static getResourcePath(log) {
5762
+ return log.metadata.requestMetadata.url.pathname;
4151
5763
  }
4152
- /**
4153
- * @private
4154
- */
4155
- loadData(httpResponseMock) {
4156
- const responseBody = httpResponseMock.body;
4157
- return (responseBody instanceof Observable) ? responseBody : of(responseBody);
5764
+ }
5765
+
5766
+ /**
5767
+ * @license
5768
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5769
+ *
5770
+ * Use of this source code is governed by an MIT-style license that can be found in
5771
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5772
+ */
5773
+ const IMG_TYPE = 'image/';
5774
+ const SVG_TYPE = 'svg/';
5775
+ class AtxResponsePreviewRendererComponent {
5776
+ set data(value) {
5777
+ const body = value.body;
5778
+ this.revokeObjectURL();
5779
+ this.response = value;
5780
+ this.json = this.text = this.imgUrl = this.trustUrl = null;
5781
+ if (body) {
5782
+ const bodyType = DataUtil.getBodyType(body);
5783
+ if (bodyType === ConsoleBodyType.TEXT)
5784
+ this.text = body;
5785
+ else if (bodyType === ConsoleBodyType.JSON)
5786
+ this.json = body;
5787
+ else if (bodyType === ConsoleBodyType.BLOB) {
5788
+ if (body.type.startsWith(IMG_TYPE) ||
5789
+ body.type.startsWith(SVG_TYPE)) {
5790
+ this.resourceName = UrlUtil.getResourceNameFromPath(value.url);
5791
+ const url = URL.createObjectURL(body);
5792
+ this.imgUrl = url;
5793
+ this.trustUrl = this.sanitizer.bypassSecurityTrustUrl(url);
5794
+ }
5795
+ }
5796
+ }
5797
+ this._cdr.detectChanges();
4158
5798
  }
4159
- /**
4160
- * @private
4161
- */
4162
- setDataStorage(responseMock, data = null) {
4163
- this._dataStorage = DataStorageBuilder.buildDataStorage(responseMock, data);
5799
+ constructor(_cdr, sanitizer) {
5800
+ this._cdr = _cdr;
5801
+ this.sanitizer = sanitizer;
5802
+ this.json = null;
5803
+ this.text = null;
5804
+ this.response = null;
5805
+ this.imgUrl = null;
5806
+ this.trustUrl = null;
4164
5807
  }
4165
- /**
4166
- * @private
4167
- */
4168
- buildHttpRequest(body) {
4169
- let params = new HttpParams();
4170
- const it = this._routeConfig.searchParams.entries();
4171
- for (const pair of it)
4172
- params = params.set(pair[0], pair[1]);
4173
- return new HttpRequest(this._method, this._url, body, { params: params });
5808
+ ngOnDestroy() {
5809
+ this.revokeObjectURL();
5810
+ this.json = this.text = this.imgUrl = this.trustUrl = null;
5811
+ }
5812
+ revokeObjectURL() {
5813
+ if (this.imgUrl)
5814
+ URL.revokeObjectURL(this.imgUrl);
5815
+ }
5816
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxResponsePreviewRendererComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1$2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); }
5817
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.3", type: AtxResponsePreviewRendererComponent, isStandalone: true, selector: "atx-response-preview-renderer", inputs: { data: "data" }, ngImport: i0, template: "\r\n<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n@if (response) {\r\n @if (text) {\r\n <section class=\"content\" [innerHTML]=\"text | safeHtml \"></section>\r\n } @else if (json) {\r\n <section class=\"content\">\r\n <atx-json-viewer [data]=\"json\"/>\r\n </section>\r\n } @else if (imgUrl) {\r\n <section class=\"content img-preview\">\r\n <div>\r\n <img [src]=\"imgUrl\" (load)=\"revokeObjectURL()\" [alt]=\"resourceName\" [title]=\"resourceName\">\r\n </div>\r\n </section>\r\n } @else {\r\n <section class=\"content center-content\">\r\n <strong>Preview not available</strong>\r\n </section>\r\n }\r\n}\r\n", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}::ng-deep .xdebug-error{font-size:12px!important}.img-preview{text-align:center}.img-preview div{box-shadow:0 4px 10px #000000bf;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUAQMAAAC3R49OAAAABlBMVEX////09PQtDxrOAAAAE0lEQVQI12P4f4CBKMxg/4EYDAAFkR1NiYvv7QAAAABJRU5ErkJggg==);background-image:linear-gradient(45deg,#F0F0F0 25%,transparent 25%),linear-gradient(-45deg,#F0F0F0 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#F0F0F0 75%),linear-gradient(-45deg,transparent 75%,#F0F0F0 75%);background-size:20px 20px;background-position:0 0,0 10px,10px -10px,-10px 0px;display:inline-block}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"], dependencies: [{ kind: "component", type: AtxJsonViewerComponent, selector: "atx-json-viewer", inputs: ["data"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5818
+ }
5819
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxResponsePreviewRendererComponent, decorators: [{
5820
+ type: Component,
5821
+ args: [{ selector: 'atx-response-preview-renderer', standalone: true, imports: [
5822
+ AtxJsonViewerComponent,
5823
+ SafeHtmlPipe
5824
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "\r\n<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n@if (response) {\r\n @if (text) {\r\n <section class=\"content\" [innerHTML]=\"text | safeHtml \"></section>\r\n } @else if (json) {\r\n <section class=\"content\">\r\n <atx-json-viewer [data]=\"json\"/>\r\n </section>\r\n } @else if (imgUrl) {\r\n <section class=\"content img-preview\">\r\n <div>\r\n <img [src]=\"imgUrl\" (load)=\"revokeObjectURL()\" [alt]=\"resourceName\" [title]=\"resourceName\">\r\n </div>\r\n </section>\r\n } @else {\r\n <section class=\"content center-content\">\r\n <strong>Preview not available</strong>\r\n </section>\r\n }\r\n}\r\n", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}::ng-deep .xdebug-error{font-size:12px!important}.img-preview{text-align:center}.img-preview div{box-shadow:0 4px 10px #000000bf;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUAQMAAAC3R49OAAAABlBMVEX////09PQtDxrOAAAAE0lEQVQI12P4f4CBKMxg/4EYDAAFkR1NiYvv7QAAAABJRU5ErkJggg==);background-image:linear-gradient(45deg,#F0F0F0 25%,transparent 25%),linear-gradient(-45deg,#F0F0F0 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#F0F0F0 75%),linear-gradient(-45deg,transparent 75%,#F0F0F0 75%);background-size:20px 20px;background-position:0 0,0 10px,10px -10px,-10px 0px;display:inline-block}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }]
5825
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1$2.DomSanitizer }], propDecorators: { data: [{
5826
+ type: Input
5827
+ }] } });
5828
+
5829
+ /**
5830
+ * @license
5831
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5832
+ *
5833
+ * Use of this source code is governed by an MIT-style license that can be found in
5834
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5835
+ */
5836
+ class AtxResponseBodyRendererComponent {
5837
+ set data(value) {
5838
+ this.body = value;
5839
+ this.text = this.blob = this.arrayBuffer = null;
5840
+ if (value) {
5841
+ const bodyType = DataUtil.getBodyType(value);
5842
+ if (bodyType === ConsoleBodyType.TEXT)
5843
+ this.text = value;
5844
+ else if (bodyType === ConsoleBodyType.JSON)
5845
+ this.text = JSON.stringify(value);
5846
+ else if (bodyType === ConsoleBodyType.BLOB)
5847
+ this.blob = value;
5848
+ else if (bodyType === ConsoleBodyType.ARRAY_BUFFER)
5849
+ this.arrayBuffer = value;
5850
+ }
5851
+ this._cdr.detectChanges();
5852
+ }
5853
+ constructor(_cdr) {
5854
+ this._cdr = _cdr;
5855
+ this.text = null;
5856
+ this.body = null;
5857
+ this.blob = null;
5858
+ this.arrayBuffer = null;
4174
5859
  }
5860
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxResponseBodyRendererComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
5861
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.3", type: AtxResponseBodyRendererComponent, isStandalone: true, selector: "atx-response-body-renderer", inputs: { data: "data" }, ngImport: i0, template: "\r\n<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n@if (body) {\r\n <section class=\"content\">\r\n @if (text) {\r\n {{ text }}\r\n } @else if (blob) {\r\n <dl>\r\n <dt>Binary data:</dt>\r\n <dd>Blob</dd>\r\n </dl>\r\n <dl>\r\n <dt>ize:</dt>\r\n <dd>{{ blob.size }}</dd>\r\n </dl>\r\n <dl>\r\n <dt>type:</dt>\r\n <dd>{{ blob.type }}</dd>\r\n </dl>\r\n } @else if (arrayBuffer) {\r\n <dl>\r\n <dt>Binary data:</dt>\r\n <dd>Array Buffer</dd>\r\n </dl>\r\n <dl>\r\n <dt>byte length:</dt>\r\n <dd>{{ arrayBuffer.byteLength }}</dd>\r\n </dl>\r\n } @else {\r\n <div class=\"center-content\">\r\n <strong>This request has no data available</strong>\r\n </div>\r\n }\r\n </section>\r\n}\r\n", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}dl,dd,dt{margin:0;padding:0}dl{display:flex;gap:12px}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5862
+ }
5863
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxResponseBodyRendererComponent, decorators: [{
5864
+ type: Component,
5865
+ args: [{ selector: 'atx-response-body-renderer', standalone: true, imports: [
5866
+ AtxJsonViewerComponent,
5867
+ SafeHtmlPipe
5868
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "\r\n<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n@if (body) {\r\n <section class=\"content\">\r\n @if (text) {\r\n {{ text }}\r\n } @else if (blob) {\r\n <dl>\r\n <dt>Binary data:</dt>\r\n <dd>Blob</dd>\r\n </dl>\r\n <dl>\r\n <dt>ize:</dt>\r\n <dd>{{ blob.size }}</dd>\r\n </dl>\r\n <dl>\r\n <dt>type:</dt>\r\n <dd>{{ blob.type }}</dd>\r\n </dl>\r\n } @else if (arrayBuffer) {\r\n <dl>\r\n <dt>Binary data:</dt>\r\n <dd>Array Buffer</dd>\r\n </dl>\r\n <dl>\r\n <dt>byte length:</dt>\r\n <dd>{{ arrayBuffer.byteLength }}</dd>\r\n </dl>\r\n } @else {\r\n <div class=\"center-content\">\r\n <strong>This request has no data available</strong>\r\n </div>\r\n }\r\n </section>\r\n}\r\n", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}dl,dd,dt{margin:0;padding:0}dl{display:flex;gap:12px}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }]
5869
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { data: [{
5870
+ type: Input
5871
+ }] } });
5872
+
5873
+ /**
5874
+ * @license
5875
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5876
+ *
5877
+ * Use of this source code is governed by an MIT-style license that can be found in
5878
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5879
+ */
5880
+ class AtxRequestDetailsComponent {
5881
+ set log(value) {
5882
+ this.currLog = value;
5883
+ if (value) {
5884
+ const metadata = value.metadata;
5885
+ const request = metadata.request;
5886
+ this.request = request;
5887
+ this.response = metadata.response;
5888
+ this.requestMetadata = metadata.requestMetadata;
5889
+ this.checkPayload(request);
5890
+ this._cdr.detectChanges();
5891
+ return;
5892
+ }
5893
+ this.hasPayload = false;
5894
+ this.request = null;
5895
+ this.response = null;
5896
+ this.requestMetadata = null;
5897
+ this._cdr.detectChanges();
5898
+ }
5899
+ constructor(_cdr) {
5900
+ this._cdr = _cdr;
5901
+ this.close = new EventEmitter(true);
5902
+ this.currLog = null;
5903
+ this.hasPayload = false;
5904
+ this.currSection = 0;
5905
+ }
5906
+ changeSection(idx) {
5907
+ this.currSection = idx;
5908
+ }
5909
+ checkPayload(request) {
5910
+ const hasBody = (request.body !== null && request !== undefined);
5911
+ this.hasPayload = (request.params.keys().length > 0 || hasBody);
5912
+ }
5913
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxRequestDetailsComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
5914
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.3", type: AtxRequestDetailsComponent, isStandalone: true, selector: "atx-monitoring-console-details", inputs: { log: "log" }, outputs: { close: "close" }, ngImport: i0, template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n@if (currLog) {\r\n <header>\r\n <menu>\r\n <li role=\"button\" (click)=\"changeSection(0)\"><span [class.selected]=\"currSection === 0\">Headers</span></li>\r\n @if (hasPayload) {\r\n <li role=\"button\" (click)=\"changeSection(1)\"><span [class.selected]=\"currSection === 1\">Payload</span></li>\r\n }\r\n <li role=\"button\" (click)=\"changeSection(2)\"><span [class.selected]=\"currSection === 2\">Preview</span></li>\r\n <li role=\"button\" (click)=\"changeSection(3)\"><span [class.selected]=\"currSection === 3\">Response</span></li>\r\n <li role=\"button\" (click)=\"changeSection(4)\"><span [class.selected]=\"currSection === 4\">Timing</span></li>\r\n <div role=\"button\" (click)=\"close.emit()\" title=\"Close\" class=\"header-btn\">\r\n <svg width=\"20\" height=\"20\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708\"/>\r\n </svg>\r\n </div>\r\n </menu>\r\n </header>\r\n <main>\r\n @if (currSection === 0) {\r\n <details open>\r\n <summary>General</summary>\r\n <section>\r\n <dl>\r\n <dt>Request URL:</dt>\r\n <dd>{{ request.url }}</dd>\r\n </dl>\r\n <dl>\r\n <dt>Request Method:</dt>\r\n <dd>{{ request.method }}</dd>\r\n </dl>\r\n <dl>\r\n <dt>Status Code:</dt>\r\n <dd>\r\n @if (response) {\r\n <svg [ngStyle]=\"{ fill: response.status < 400 ? 'green' : 'red' }\" \r\n width=\"13\" height=\"13\" viewBox=\"0 0 16 16\">\r\n <circle cx=\"8\" cy=\"8\" r=\"8\"/>\r\n </svg>\r\n {{ response.status }} {{ response.statusText }}\r\n } @else {\r\n <svg fill=\"orange\" width=\"13\" height=\"13\" viewBox=\"0 0 16 16\">\r\n <circle cx=\"8\" cy=\"8\" r=\"8\"/>\r\n </svg>\r\n prefetch\r\n }\r\n </dd>\r\n </dl>\r\n </section>\r\n </details>\r\n <details>\r\n <summary>Response Headers</summary>\r\n <section>\r\n @if (response) {\r\n @for( item of response.headers.keys(); track item) {\r\n <dl>\r\n <dt>{{ item }}</dt>\r\n <dd>{{ response.headers.get(item) }}</dd>\r\n </dl>\r\n \r\n }\r\n }\r\n </section>\r\n </details>\r\n <details>\r\n <summary>Request Headers</summary>\r\n <section>\r\n @for( item of request.headers.keys(); track item) {\r\n <dl>\r\n <dt>{{ item }}</dt>\r\n <dd>{{ request.headers.get(item) }}</dd>\r\n </dl>\r\n }\r\n </section>\r\n </details>\r\n } @else if (currSection === 1) {\r\n <atx-payload-renderer [log]=\"currLog\"/>\r\n } @else if (currSection === 2 && response) {\r\n <atx-response-preview-renderer [data]=\"response\"/>\r\n } @else if (currSection === 3 && response) {\r\n <section class=\"raw-response\">\r\n <atx-response-body-renderer [data]=\"response.body\"/>\r\n </section>\r\n } @else if (currSection === 4 && response) {\r\n <atx-timing-renderer [data]=\"currLog\"/>\r\n }\r\n </main>\r\n}\r\n", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}:host{position:relative;width:100%;height:100%}header{padding:0;margin:0 0 6px;-webkit-user-select:none;user-select:none;position:absolute;width:100%}header menu{background-color:var(--background-color);border:1px solid var(--border-color)}header menu li{padding:0 0 0 6px}header menu .selected{border-bottom:2px solid var(--border-color)}main{position:absolute;width:100%;top:36px;bottom:0;overflow-y:auto}details summary{padding:2px 6px;background-color:var(--background-color);border:1px solid var(--border-color);-webkit-user-select:none;user-select:none;margin-bottom:6px}details section{padding:4px 6px}details section dl{display:flex;gap:10px}details section dl,details section dt,details section dd{padding:0;margin:0}details section dt{min-width:200px}.status-indicator{padding:0;margin:0}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: AtxPayloadRendererComponent, selector: "atx-payload-renderer", inputs: ["log"] }, { kind: "component", type: AtxTimingRendererComponent, selector: "atx-timing-renderer", inputs: ["data"] }, { kind: "component", type: AtxResponsePreviewRendererComponent, selector: "atx-response-preview-renderer", inputs: ["data"] }, { kind: "component", type: AtxResponseBodyRendererComponent, selector: "atx-response-body-renderer", inputs: ["data"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4175
5915
  }
5916
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxRequestDetailsComponent, decorators: [{
5917
+ type: Component,
5918
+ args: [{ selector: 'atx-monitoring-console-details', standalone: true, imports: [
5919
+ NgStyle,
5920
+ AtxJsonViewerComponent,
5921
+ AtxPayloadRendererComponent,
5922
+ AtxTimingRendererComponent,
5923
+ AtxResponsePreviewRendererComponent,
5924
+ AtxResponseBodyRendererComponent
5925
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n@if (currLog) {\r\n <header>\r\n <menu>\r\n <li role=\"button\" (click)=\"changeSection(0)\"><span [class.selected]=\"currSection === 0\">Headers</span></li>\r\n @if (hasPayload) {\r\n <li role=\"button\" (click)=\"changeSection(1)\"><span [class.selected]=\"currSection === 1\">Payload</span></li>\r\n }\r\n <li role=\"button\" (click)=\"changeSection(2)\"><span [class.selected]=\"currSection === 2\">Preview</span></li>\r\n <li role=\"button\" (click)=\"changeSection(3)\"><span [class.selected]=\"currSection === 3\">Response</span></li>\r\n <li role=\"button\" (click)=\"changeSection(4)\"><span [class.selected]=\"currSection === 4\">Timing</span></li>\r\n <div role=\"button\" (click)=\"close.emit()\" title=\"Close\" class=\"header-btn\">\r\n <svg width=\"20\" height=\"20\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708\"/>\r\n </svg>\r\n </div>\r\n </menu>\r\n </header>\r\n <main>\r\n @if (currSection === 0) {\r\n <details open>\r\n <summary>General</summary>\r\n <section>\r\n <dl>\r\n <dt>Request URL:</dt>\r\n <dd>{{ request.url }}</dd>\r\n </dl>\r\n <dl>\r\n <dt>Request Method:</dt>\r\n <dd>{{ request.method }}</dd>\r\n </dl>\r\n <dl>\r\n <dt>Status Code:</dt>\r\n <dd>\r\n @if (response) {\r\n <svg [ngStyle]=\"{ fill: response.status < 400 ? 'green' : 'red' }\" \r\n width=\"13\" height=\"13\" viewBox=\"0 0 16 16\">\r\n <circle cx=\"8\" cy=\"8\" r=\"8\"/>\r\n </svg>\r\n {{ response.status }} {{ response.statusText }}\r\n } @else {\r\n <svg fill=\"orange\" width=\"13\" height=\"13\" viewBox=\"0 0 16 16\">\r\n <circle cx=\"8\" cy=\"8\" r=\"8\"/>\r\n </svg>\r\n prefetch\r\n }\r\n </dd>\r\n </dl>\r\n </section>\r\n </details>\r\n <details>\r\n <summary>Response Headers</summary>\r\n <section>\r\n @if (response) {\r\n @for( item of response.headers.keys(); track item) {\r\n <dl>\r\n <dt>{{ item }}</dt>\r\n <dd>{{ response.headers.get(item) }}</dd>\r\n </dl>\r\n \r\n }\r\n }\r\n </section>\r\n </details>\r\n <details>\r\n <summary>Request Headers</summary>\r\n <section>\r\n @for( item of request.headers.keys(); track item) {\r\n <dl>\r\n <dt>{{ item }}</dt>\r\n <dd>{{ request.headers.get(item) }}</dd>\r\n </dl>\r\n }\r\n </section>\r\n </details>\r\n } @else if (currSection === 1) {\r\n <atx-payload-renderer [log]=\"currLog\"/>\r\n } @else if (currSection === 2 && response) {\r\n <atx-response-preview-renderer [data]=\"response\"/>\r\n } @else if (currSection === 3 && response) {\r\n <section class=\"raw-response\">\r\n <atx-response-body-renderer [data]=\"response.body\"/>\r\n </section>\r\n } @else if (currSection === 4 && response) {\r\n <atx-timing-renderer [data]=\"currLog\"/>\r\n }\r\n </main>\r\n}\r\n", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}:host{position:relative;width:100%;height:100%}header{padding:0;margin:0 0 6px;-webkit-user-select:none;user-select:none;position:absolute;width:100%}header menu{background-color:var(--background-color);border:1px solid var(--border-color)}header menu li{padding:0 0 0 6px}header menu .selected{border-bottom:2px solid var(--border-color)}main{position:absolute;width:100%;top:36px;bottom:0;overflow-y:auto}details summary{padding:2px 6px;background-color:var(--background-color);border:1px solid var(--border-color);-webkit-user-select:none;user-select:none;margin-bottom:6px}details section{padding:4px 6px}details section dl{display:flex;gap:10px}details section dl,details section dt,details section dd{padding:0;margin:0}details section dt{min-width:200px}.status-indicator{padding:0;margin:0}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }]
5926
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { close: [{
5927
+ type: Output
5928
+ }], log: [{
5929
+ type: Input
5930
+ }] } });
4176
5931
 
4177
5932
  /**
4178
5933
  * @license
4179
5934
  * Copyright Pascal ECHEMANN. All Rights Reserved.
4180
5935
  *
4181
- * Use of this source code is governed by an MIT-style license that can be ound in
4182
- * fthe LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5936
+ * Use of this source code is governed by an MIT-style license that can be found in
5937
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4183
5938
  */
4184
5939
  /**
4185
5940
  * @private
4186
- * An error used as reference for unit testing.
4187
- * Angular framework calls `XMLHttpRequest` method only after the `open()` method invokation.
4188
5941
  */
4189
- const XHR_ERROR = (method) => {
4190
- throw new Error(`Attempt to call ${method}() method before calling open().`);
4191
- };
5942
+ const B = " B";
4192
5943
  /**
4193
5944
  * @private
4194
- * A XHR proxy that is used by the Mocking Framework to apply HTTP call strategies.
4195
5945
  */
4196
- class XhrProxyImpl extends XhrBase {
4197
- /**
4198
- * @private
4199
- *
4200
- * XMLHTTPRequest API
4201
- */
4202
- get response() {
4203
- return this.XHR ? this.XHR.response : undefined;
4204
- }
4205
- /**
4206
- * @private
4207
- *
4208
- * XMLHTTPRequest API
4209
- */
4210
- get status() {
4211
- return this.XHR ? this.XHR.status : 0;
5946
+ const KB = " KB";
5947
+ /**
5948
+ * @private
5949
+ */
5950
+ const MB = " MB";
5951
+ class SizeUtil {
5952
+ static getSize(obj) {
5953
+ if (!obj)
5954
+ return 0;
5955
+ return new TextEncoder().encode(JSON.stringify(obj)).length;
5956
+ }
5957
+ static sizeToString(size) {
5958
+ if (size < 1024)
5959
+ return size + B;
5960
+ size = size / 1024;
5961
+ if (size < 1024)
5962
+ return size + KB;
5963
+ return (size / 1024).toFixed(2) + MB;
4212
5964
  }
4213
- /**
4214
- * @private
4215
- *
4216
- * XMLHTTPRequest API
4217
- */
4218
- get statusText() {
4219
- return this.XHR ? this.XHR.statusText : EMPTY_STRING;
5965
+ }
5966
+
5967
+ /**
5968
+ * @license
5969
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5970
+ *
5971
+ * Use of this source code is governed by an MIT-style license that can be found in
5972
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
5973
+ */
5974
+ class AtxConsoleFooterComponent {
5975
+ constructor() {
5976
+ this.size = "0 B";
5977
+ this.numLogs = 0;
4220
5978
  }
4221
- /**
4222
- * @private
4223
- *
4224
- * XMLHTTPRequest API
4225
- */
4226
- get readyState() {
4227
- return this.XHR ? this.XHR.readyState : this.UNSENT;
5979
+ set cumulativeSize(value) {
5980
+ this.size = SizeUtil.sizeToString(value);
4228
5981
  }
4229
- /**
4230
- * @private
4231
- *
4232
- * XMLHTTPRequest API
4233
- */
4234
- get responseURL() {
4235
- return this.XHR ? this.XHR.responseURL : EMPTY_STRING;
5982
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxConsoleFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5983
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.0.3", type: AtxConsoleFooterComponent, isStandalone: true, selector: "atx-console-footer", inputs: { cumulativeSize: "cumulativeSize", numLogs: "numLogs" }, ngImport: i0, template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n<footer>\r\n <div>\r\n {{ numLogs }} requests\r\n </div>\r\n <div class=\"menu-separator\"></div>\r\n <div>\r\n {{ size }} resources\r\n </div>\r\n</footer>\r\n", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}footer{background-color:var(--light-gray);border-top:1px solid var(--border-color);margin-top:6px;padding:6px 6px 6px 10px;display:flex;align-items:center;gap:6px}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }); }
5984
+ }
5985
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxConsoleFooterComponent, decorators: [{
5986
+ type: Component,
5987
+ args: [{ selector: 'atx-console-footer', standalone: true, imports: [], template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n<footer>\r\n <div>\r\n {{ numLogs }} requests\r\n </div>\r\n <div class=\"menu-separator\"></div>\r\n <div>\r\n {{ size }} resources\r\n </div>\r\n</footer>\r\n", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}footer{background-color:var(--light-gray);border-top:1px solid var(--border-color);margin-top:6px;padding:6px 6px 6px 10px;display:flex;align-items:center;gap:6px}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }]
5988
+ }], propDecorators: { cumulativeSize: [{
5989
+ type: Input
5990
+ }], numLogs: [{
5991
+ type: Input
5992
+ }] } });
5993
+
5994
+ /**
5995
+ * @license
5996
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
5997
+ *
5998
+ * Use of this source code is governed by an MIT-style license that can be found in
5999
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6000
+ */
6001
+ var AtxConsoleActionType;
6002
+ (function (AtxConsoleActionType) {
6003
+ AtxConsoleActionType[AtxConsoleActionType["CLEAR_LOGS"] = 0] = "CLEAR_LOGS";
6004
+ AtxConsoleActionType[AtxConsoleActionType["EXPORT_LOGS"] = 1] = "EXPORT_LOGS";
6005
+ AtxConsoleActionType[AtxConsoleActionType["IMPORT_LOGS"] = 2] = "IMPORT_LOGS";
6006
+ })(AtxConsoleActionType || (AtxConsoleActionType = {}));
6007
+
6008
+ /**
6009
+ * @license
6010
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
6011
+ *
6012
+ * Use of this source code is governed by an MIT-style license that can be found in
6013
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6014
+ */
6015
+ class AtxConsoleMenuComponent {
6016
+ constructor(logger) {
6017
+ this.logger = logger;
6018
+ this.actionList = AtxConsoleActionType;
6019
+ this.action = new EventEmitter(true);
4236
6020
  }
4237
- /**
4238
- * @private
4239
- *
4240
- * XMLHTTPRequest API
4241
- */
4242
- get responseText() {
4243
- return this.XHR ? this.XHR.responseText : EMPTY_STRING;
6021
+ sendAction(type) {
6022
+ this.action.emit({ type: type });
4244
6023
  }
4245
- /**
4246
- * @private
4247
- *
4248
- * XMLHTTPRequest API
4249
- */
4250
- get responseType() {
4251
- return this.XHR ? this.XHR.responseType : EMPTY_STRING;
6024
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxConsoleMenuComponent, deps: [{ token: HttpMockLoggingService }], target: i0.ɵɵFactoryTarget.Component }); }
6025
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.0.3", type: AtxConsoleMenuComponent, isStandalone: true, selector: "atx-console-menu", outputs: { action: "action" }, ngImport: i0, template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n \r\n<menu>\r\n <li role=\"button\" title=\"Clear network log\" (click)=\"sendAction(actionList.CLEAR_LOGS)\">\r\n <svg width=\"18\" height=\"18\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16\"/>\r\n <path d=\"M11.354 4.646a.5.5 0 0 0-.708 0l-6 6a.5.5 0 0 0 .708.708l6-6a.5.5 0 0 0 0-.708\"/>\r\n </svg>\r\n </li>\r\n <div class=\"menu-separator\"></div>\r\n <li title=\"Filter\" class=\"disabled\">\r\n <svg width=\"19\" height=\"19\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.692V13.5a.5.5 0 0 1-.342.474l-3 1A.5.5 0 0 1 6 14.5V8.692L1.628 3.834A.5.5 0 0 1 1.5 3.5zm1 .5v1.308l4.372 4.858A.5.5 0 0 1 7 8.5v5.306l2-.666V8.5a.5.5 0 0 1 .128-.334L13.5 3.308V2z\"/>\r\n </svg>\r\n </li>\r\n <li title=\"Search\" class=\"disabled\">\r\n <svg width=\"18\" height=\"18\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001q.044.06.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1 1 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0\"/>\r\n </svg>\r\n </li>\r\n <div class=\"menu-separator\"></div>\r\n <li role=\"button\" title=\"Import\" (click)=\"sendAction(actionList.IMPORT_LOGS)\">\r\n <svg width=\"19\" height=\"19\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5\"/>\r\n <path d=\"M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708z\"/>\r\n </svg>\r\n </li>\r\n <li role=\"button\" title=\"Export\" (click)=\"sendAction(actionList.EXPORT_LOGS)\">\r\n <svg width=\"18\" height=\"18\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5\"/>\r\n <path d=\"M7.646 1.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 2.707V11.5a.5.5 0 0 1-1 0V2.707L5.354 4.854a.5.5 0 1 1-.708-.708z\"/>\r\n </svg>\r\n </li>\r\n</menu>\r\n", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}menu{padding-left:6px;background-color:var(--light-gray);position:absolute;width:100%;border-bottom:1px solid var(--border-color)}menu li{padding:6px}menu li:hover:not(.disabled){background-color:var(--dark-gray)}menu .disabled{opacity:.25}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }); }
6026
+ }
6027
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxConsoleMenuComponent, decorators: [{
6028
+ type: Component,
6029
+ args: [{ selector: 'atx-console-menu', standalone: true, imports: [], template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n \r\n<menu>\r\n <li role=\"button\" title=\"Clear network log\" (click)=\"sendAction(actionList.CLEAR_LOGS)\">\r\n <svg width=\"18\" height=\"18\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16\"/>\r\n <path d=\"M11.354 4.646a.5.5 0 0 0-.708 0l-6 6a.5.5 0 0 0 .708.708l6-6a.5.5 0 0 0 0-.708\"/>\r\n </svg>\r\n </li>\r\n <div class=\"menu-separator\"></div>\r\n <li title=\"Filter\" class=\"disabled\">\r\n <svg width=\"19\" height=\"19\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.692V13.5a.5.5 0 0 1-.342.474l-3 1A.5.5 0 0 1 6 14.5V8.692L1.628 3.834A.5.5 0 0 1 1.5 3.5zm1 .5v1.308l4.372 4.858A.5.5 0 0 1 7 8.5v5.306l2-.666V8.5a.5.5 0 0 1 .128-.334L13.5 3.308V2z\"/>\r\n </svg>\r\n </li>\r\n <li title=\"Search\" class=\"disabled\">\r\n <svg width=\"18\" height=\"18\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001q.044.06.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1 1 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0\"/>\r\n </svg>\r\n </li>\r\n <div class=\"menu-separator\"></div>\r\n <li role=\"button\" title=\"Import\" (click)=\"sendAction(actionList.IMPORT_LOGS)\">\r\n <svg width=\"19\" height=\"19\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5\"/>\r\n <path d=\"M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708z\"/>\r\n </svg>\r\n </li>\r\n <li role=\"button\" title=\"Export\" (click)=\"sendAction(actionList.EXPORT_LOGS)\">\r\n <svg width=\"18\" height=\"18\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5\"/>\r\n <path d=\"M7.646 1.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 2.707V11.5a.5.5 0 0 1-1 0V2.707L5.354 4.854a.5.5 0 1 1-.708-.708z\"/>\r\n </svg>\r\n </li>\r\n</menu>\r\n", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}menu{padding-left:6px;background-color:var(--light-gray);position:absolute;width:100%;border-bottom:1px solid var(--border-color)}menu li{padding:6px}menu li:hover:not(.disabled){background-color:var(--dark-gray)}menu .disabled{opacity:.25}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }]
6030
+ }], ctorParameters: () => [{ type: HttpMockLoggingService }], propDecorators: { action: [{
6031
+ type: Output
6032
+ }] } });
6033
+
6034
+ /**
6035
+ * @license
6036
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
6037
+ *
6038
+ * Use of this source code is governed by an MIT-style license that can be found in
6039
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6040
+ */
6041
+ class LogMessageUtil {
6042
+ static getMessageFromLevel(level) {
6043
+ if (level === LogLevel.INFO)
6044
+ return HttpMockLoggingConstant.RESPONSE_MESSAGE;
6045
+ if (level === LogLevel.ERROR)
6046
+ return HttpMockLoggingConstant.ERROR_MESSAGE;
6047
+ return HttpMockLoggingConstant.CONFIG_MESSAGE;
4252
6048
  }
4253
- /**
4254
- * @private
4255
- *
4256
- * XMLHTTPRequest API
4257
- */
4258
- set responseType(value) {
4259
- if (!this.XHR)
4260
- XHR_ERROR("responseType");
4261
- this.XHR.responseType = value;
6049
+ }
6050
+
6051
+ /**
6052
+ * @license
6053
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
6054
+ *
6055
+ * Use of this source code is governed by an MIT-style license that can be found in
6056
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6057
+ */
6058
+ class RequestMetadataConverter {
6059
+ static requestMetadataToDto(metadata) {
6060
+ return {
6061
+ duration: metadata.duration,
6062
+ id: metadata.id.toString(),
6063
+ stalled: metadata.stalled,
6064
+ start: metadata.start,
6065
+ url: metadata.url.toString()
6066
+ };
4262
6067
  }
4263
- get upload() {
4264
- return this.XHR.upload;
6068
+ static dtoToRequestMetadata(metadata) {
6069
+ return {
6070
+ duration: metadata.duration,
6071
+ id: Uuid.fromString(metadata.id),
6072
+ stalled: metadata.stalled,
6073
+ start: metadata.start,
6074
+ url: new URL(metadata.url)
6075
+ };
4265
6076
  }
4266
- open(method, url, async, username, password) {
4267
- const m = method.toString().toLowerCase();
4268
- const parsedUrl = URL.canParse(url) ? new URL(url) : new URL(this._httpMockService.getAppOrigin() + url);
4269
- const config = this._httpMockService.getRouteConfig(parsedUrl, m);
4270
- if (this.XHR && this.XHR instanceof DelegateXhr)
4271
- this.XHR.destroy();
4272
- this.XHR = config ? new DelegateXhr(config) : new XMLHttpRequest();
4273
- this.XHR.withCredentials = this.withCredentials;
4274
- this.XHR.open(m.toString(), parsedUrl.toString());
6077
+ }
6078
+
6079
+ /**
6080
+ * @license
6081
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
6082
+ *
6083
+ * Use of this source code is governed by an MIT-style license that can be found in
6084
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6085
+ */
6086
+ class HttpHeadersConverter {
6087
+ static headersToDto(headers) {
6088
+ const dtoList = [];
6089
+ const keys = headers.keys();
6090
+ let cursor = keys.length - 1;
6091
+ for (; cursor >= 0; cursor--) {
6092
+ const key = keys[cursor];
6093
+ dtoList.push({
6094
+ name: key,
6095
+ value: headers.getAll(key)
6096
+ });
6097
+ }
6098
+ return dtoList;
6099
+ }
6100
+ static dtoToHeaders(headersDto) {
6101
+ let headers = new HttpHeaders();
6102
+ let cursor = headersDto.length - 1;
6103
+ for (; cursor >= 0; cursor--) {
6104
+ const entry = headersDto[cursor];
6105
+ const value = entry.value;
6106
+ if (value)
6107
+ headers = headers.append(entry.name, value);
6108
+ }
6109
+ return headers;
4275
6110
  }
4276
- /**
4277
- * @private
4278
- *
4279
- * XMLHTTPRequest API
4280
- */
4281
- abort() {
4282
- if (this.XHR)
4283
- return this.XHR.abort();
4284
- XHR_ERROR("abort");
6111
+ }
6112
+
6113
+ /**
6114
+ * @license
6115
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
6116
+ *
6117
+ * Use of this source code is governed by an MIT-style license that can be found in
6118
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6119
+ */
6120
+ class BodySerializer {
6121
+ static serialize(data, type) {
6122
+ if (type === ConsoleBodyType.TEXT)
6123
+ return data;
6124
+ if (type === ConsoleBodyType.JSON)
6125
+ return JSON.stringify(data);
6126
+ if (type === ConsoleBodyType.BLOB)
6127
+ return null;
6128
+ if (type === ConsoleBodyType.FORM_DATA)
6129
+ return JSON.stringify(Array.from(data));
6130
+ if (type === ConsoleBodyType.ARRAY_BUFFER)
6131
+ null;
6132
+ return null;
4285
6133
  }
4286
- /**
4287
- * @private
4288
- *
4289
- * XMLHTTPRequest API
4290
- */
4291
- getAllResponseHeaders() {
4292
- return this.XHR ? this.XHR.getAllResponseHeaders() : EMPTY_STRING;
6134
+ static unserialize(data, type) {
6135
+ if (type === ConsoleBodyType.TEXT)
6136
+ return data;
6137
+ if (type === ConsoleBodyType.JSON)
6138
+ return JSON.parse(data);
6139
+ if (type === ConsoleBodyType.BLOB)
6140
+ return null;
6141
+ if (type === ConsoleBodyType.FORM_DATA)
6142
+ return BodySerializer.stringToFormData(data);
6143
+ if (type === ConsoleBodyType.ARRAY_BUFFER)
6144
+ null;
6145
+ return null;
4293
6146
  }
4294
- /**
4295
- * @private
4296
- *
4297
- * XMLHTTPRequest API
4298
- */
4299
- addEventListener(type, listener, options) {
4300
- if (this.XHR)
4301
- return this.XHR.addEventListener(type, listener, options);
4302
- XHR_ERROR("addEventListener");
6147
+ static stringToFormData(data) {
6148
+ const result = new FormData();
6149
+ const arr = JSON.parse(data);
6150
+ let cursor = arr.length - 1;
6151
+ for (; cursor >= 0; cursor--) {
6152
+ const entry = arr[cursor];
6153
+ result.append(entry[0], entry[1]);
6154
+ }
6155
+ return result;
4303
6156
  }
4304
- /**
4305
- * @private
4306
- *
4307
- * XMLHTTPRequest API
4308
- */
4309
- removeEventListener(type, listener, options) {
4310
- if (this.XHR)
4311
- return this.XHR.removeEventListener(type, listener, options);
4312
- XHR_ERROR("removeEventListener");
6157
+ }
6158
+
6159
+ /**
6160
+ * @license
6161
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
6162
+ *
6163
+ * Use of this source code is governed by an MIT-style license that can be found in
6164
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6165
+ */
6166
+ class BodyConverter {
6167
+ static bodyToDto(body) {
6168
+ const bodyType = DataUtil.getBodyType(body);
6169
+ return {
6170
+ type: bodyType,
6171
+ data: BodySerializer.serialize(body, bodyType)
6172
+ };
4313
6173
  }
4314
- /**
4315
- * @private
4316
- *
4317
- * XMLHTTPRequest API
4318
- */
4319
- send(body) {
4320
- if (this.XHR)
4321
- return this.XHR.send(body);
4322
- XHR_ERROR("send");
6174
+ static dtoToBody(dto) {
6175
+ return BodySerializer.unserialize(dto.data, dto.type);
4323
6176
  }
4324
- /**
4325
- * @private
4326
- *
4327
- * XMLHTTPRequest API
4328
- */
4329
- setRequestHeader(name, value) {
4330
- if (this.XHR)
4331
- return this.XHR.setRequestHeader(name, value);
4332
- XHR_ERROR("setRequestHeader");
6177
+ }
6178
+
6179
+ /**
6180
+ * @license
6181
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
6182
+ *
6183
+ * Use of this source code is governed by an MIT-style license that can be found in
6184
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6185
+ */
6186
+ const ATX_IS_IMPORTED_LOG = new HttpContextToken(() => false);
6187
+
6188
+ /**
6189
+ * @license
6190
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
6191
+ *
6192
+ * Use of this source code is governed by an MIT-style license that can be found in
6193
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6194
+ */
6195
+ class HttpRequestConverter {
6196
+ static buildRequestDto(request) {
6197
+ return {
6198
+ body: BodyConverter.bodyToDto(request.body),
6199
+ reportProgress: request.reportProgress,
6200
+ withCredentials: request.withCredentials,
6201
+ responseType: request.responseType,
6202
+ method: request.method,
6203
+ url: request.url,
6204
+ params: request.params.toString(),
6205
+ headers: HttpHeadersConverter.headersToDto(request.headers)
6206
+ };
4333
6207
  }
4334
- /**
4335
- * @private
4336
- *
4337
- * For Unit Testing only.
4338
- */
4339
- instanceOf(classRef) {
4340
- return this.XHR instanceof classRef;
6208
+ static buildHttpRequest(dto) {
6209
+ const ctx = new HttpContext();
6210
+ const paramsOpt = {
6211
+ fromString: dto.params
6212
+ };
6213
+ const init = {
6214
+ headers: HttpHeadersConverter.dtoToHeaders(dto.headers),
6215
+ reportProgress: dto.reportProgress,
6216
+ responseType: dto.responseType,
6217
+ withCredentials: dto.withCredentials,
6218
+ params: new HttpParams(paramsOpt),
6219
+ context: ctx
6220
+ };
6221
+ const body = BodyConverter.dtoToBody(dto.body);
6222
+ const request = new HttpRequest(dto.method, dto.url, body, init);
6223
+ ctx.set(ATX_IS_IMPORTED_LOG, true);
6224
+ return request;
4341
6225
  }
4342
- /**
4343
- * @private
4344
- */
4345
- constructor(_httpMockService) {
4346
- super();
4347
- this._httpMockService = _httpMockService;
6226
+ }
6227
+
6228
+ /**
6229
+ * @license
6230
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
6231
+ *
6232
+ * Use of this source code is governed by an MIT-style license that can be found in
6233
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
6234
+ */
6235
+ class HttpResponseConverter {
6236
+ static buildResponseDto(response) {
6237
+ return {
6238
+ body: BodyConverter.bodyToDto(response.body),
6239
+ headers: HttpHeadersConverter.headersToDto(response.headers),
6240
+ status: response.status,
6241
+ statusText: response.statusText,
6242
+ url: response.url
6243
+ };
6244
+ }
6245
+ static buildHttpResponse(dto) {
6246
+ const init = {
6247
+ body: BodyConverter.dtoToBody(dto.body),
6248
+ headers: HttpHeadersConverter.dtoToHeaders(dto.headers),
6249
+ status: dto.status,
6250
+ statusText: dto.statusText,
6251
+ url: dto.url
6252
+ };
6253
+ return new HttpResponse(init);
4348
6254
  }
4349
6255
  }
4350
6256
 
@@ -4355,23 +6261,48 @@ class XhrProxyImpl extends XhrBase {
4355
6261
  * Use of this source code is governed by an MIT-style license that can be found in
4356
6262
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4357
6263
  */
6264
+ class LogMetadataConverter {
6265
+ static metadataToDto(metadata) {
6266
+ return {
6267
+ request: HttpRequestConverter.buildRequestDto(metadata.request),
6268
+ response: HttpResponseConverter.buildResponseDto(metadata.response),
6269
+ requestMetadata: RequestMetadataConverter.requestMetadataToDto(metadata.requestMetadata)
6270
+ };
6271
+ }
6272
+ static dtoToMetadata(dto) {
6273
+ return {
6274
+ request: HttpRequestConverter.buildHttpRequest(dto.request),
6275
+ response: HttpResponseConverter.buildHttpResponse(dto.response),
6276
+ requestMetadata: RequestMetadataConverter.dtoToRequestMetadata(dto.requestMetadata)
6277
+ };
6278
+ }
6279
+ }
6280
+
4358
6281
  /**
4359
- * @private
4360
- * The concrete implementation of the `XhrFactory` interface.
6282
+ * @license
6283
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
6284
+ *
6285
+ * Use of this source code is governed by an MIT-style license that can be found in
6286
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4361
6287
  */
4362
- class XhrProxyFactoryImpl extends XhrFactory {
4363
- /**
4364
- * @private
4365
- */
4366
- constructor(_httpMockService) {
4367
- super();
4368
- this._httpMockService = _httpMockService;
6288
+ class LogConverter {
6289
+ logToDto(log) {
6290
+ return {
6291
+ level: log.level,
6292
+ timestamp: log.timestamp,
6293
+ metadata: LogMetadataConverter.metadataToDto(log.metadata)
6294
+ };
4369
6295
  }
4370
- /**
4371
- * @private
4372
- */
4373
- build() {
4374
- return new XhrProxyImpl(this._httpMockService);
6296
+ dtoToLog(dto) {
6297
+ const level = dto.level;
6298
+ const log = {
6299
+ caller: HttpMockLoggingConstant.CALLER,
6300
+ level: level,
6301
+ timestamp: dto.timestamp,
6302
+ message: LogMessageUtil.getMessageFromLevel(level),
6303
+ metadata: LogMetadataConverter.dtoToMetadata(dto.metadata)
6304
+ };
6305
+ return log;
4375
6306
  }
4376
6307
  }
4377
6308
 
@@ -4382,45 +6313,226 @@ class XhrProxyFactoryImpl extends XhrFactory {
4382
6313
  * Use of this source code is governed by an MIT-style license that can be found in
4383
6314
  * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4384
6315
  */
6316
+ class AtxLogIoService {
6317
+ constructor(_logger) {
6318
+ this._logger = _logger;
6319
+ this._converter = new LogConverter();
6320
+ }
6321
+ exportFile(logs) {
6322
+ const logDtoList = [];
6323
+ let cursor = logs.length - 1;
6324
+ for (; cursor >= 0; cursor--) {
6325
+ const log = logs[cursor];
6326
+ if (log.level !== LogLevel.CONFIG)
6327
+ logDtoList.push(this._converter.logToDto(log));
6328
+ }
6329
+ const exportData = {
6330
+ logs: logDtoList,
6331
+ timestamp: Date.now()
6332
+ };
6333
+ const a = document.createElement("a");
6334
+ const file = new Blob([JSON.stringify(exportData)], { type: 'application/json' });
6335
+ a.href = URL.createObjectURL(file);
6336
+ a.download = "logs.hmfl";
6337
+ a.click();
6338
+ }
6339
+ importFile() {
6340
+ const input = document.createElement("input");
6341
+ const converter = this._converter;
6342
+ const logger = this._logger;
6343
+ input.setAttribute("type", "file");
6344
+ input.setAttribute("accept", ".hmfl");
6345
+ input.onchange = (event) => {
6346
+ const fileList = event.target.files;
6347
+ const file = fileList[0];
6348
+ if (file) {
6349
+ var reader = new FileReader();
6350
+ reader.readAsText(file, "UTF-8");
6351
+ reader.onload = function (evt) {
6352
+ const result = reader.result;
6353
+ const resultLogData = JSON.parse(result);
6354
+ const logs = resultLogData.logs;
6355
+ let cursor = logs.length - 1;
6356
+ for (; cursor >= 0; cursor--) {
6357
+ const log = converter.dtoToLog(logs[cursor]);
6358
+ const metadata = log.metadata;
6359
+ const level = log.level;
6360
+ if (level === LogLevel.INFO)
6361
+ logger.info(metadata);
6362
+ else if (level === LogLevel.ERROR)
6363
+ logger.error(metadata);
6364
+ }
6365
+ ;
6366
+ };
6367
+ reader.onerror = function (e) {
6368
+ console.log(e);
6369
+ };
6370
+ }
6371
+ };
6372
+ input.click();
6373
+ }
6374
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxLogIoService, deps: [{ token: HttpMockLoggingService }], target: i0.ɵɵFactoryTarget.Injectable }); }
6375
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxLogIoService }); }
6376
+ }
6377
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxLogIoService, decorators: [{
6378
+ type: Injectable
6379
+ }], ctorParameters: () => [{ type: HttpMockLoggingService }] });
6380
+
4385
6381
  /**
4386
- * A factory function that creates and returns a new `XhrFactory` object.
6382
+ * @license
6383
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
4387
6384
  *
4388
- * @returns A new `XhrFactory` object.
6385
+ * Use of this source code is governed by an MIT-style license that can be found in
6386
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4389
6387
  */
4390
- const httpMockFactory = () => {
4391
- return new XhrProxyFactoryImpl(inject(HttpMockService));
4392
- };
6388
+ class AtxIconRendererComponent {
6389
+ constructor() {
6390
+ this.bodyType = ConsoleBodyType.INVALID;
6391
+ this.hasReponse = false;
6392
+ this.isImported = false;
6393
+ }
6394
+ set data(log) {
6395
+ const response = log.metadata.response;
6396
+ const complete = response !== null && response !== undefined;
6397
+ this.hasReponse = complete;
6398
+ if (complete)
6399
+ this.bodyType = DataUtil.getBodyType(response.body);
6400
+ this.log = log;
6401
+ this.isImported = log.metadata.request?.context.get(ATX_IS_IMPORTED_LOG);
6402
+ }
6403
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxIconRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6404
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.3", type: AtxIconRendererComponent, isStandalone: true, selector: "atx-icon-renderer", inputs: { data: "data" }, ngImport: i0, template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n@if (log) {\r\n @if (hasReponse) {\r\n <svg width=\"24\" height=\"24\" fill=\"currentColor\">\r\n @if (bodyType == 0) {\r\n <use href=\"#empty-icon\"/>\r\n } @else if (bodyType == 1) {\r\n <use href=\"#json-icon\"/>\r\n } @else if (bodyType == 2) {\r\n <use href=\"#text-icon\"/>\r\n } @else if (bodyType == 3) {\r\n <use href=\"#blob-icon\"/>\r\n } @else if (bodyType == 5) {\r\n <use href=\"#bin-icon\"/>\r\n }\r\n </svg>\r\n @if (isImported) {\r\n <svg width=\"24\" height=\"24\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path fill-rule=\"evenodd\" d=\"M3.5 6a.5.5 0 0 0-.5.5v8a.5.5 0 0 0 .5.5h9a.5.5 0 0 0 .5-.5v-8a.5.5 0 0 0-.5-.5h-2a.5.5 0 0 1 0-1h2A1.5 1.5 0 0 1 14 6.5v8a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 2 14.5v-8A1.5 1.5 0 0 1 3.5 5h2a.5.5 0 0 1 0 1z\"/>\r\n <path fill-rule=\"evenodd\" d=\"M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708z\"/>\r\n </svg>\r\n }\r\n } @else {\r\n <div class=\"spinner\">\r\n <svg width=\"20\" height=\"20\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M11.534 7h3.932a.25.25 0 0 1 .192.41l-1.966 2.36a.25.25 0 0 1-.384 0l-1.966-2.36a.25.25 0 0 1 .192-.41m-11 2h3.932a.25.25 0 0 0 .192-.41L2.692 6.23a.25.25 0 0 0-.384 0L.342 8.59A.25.25 0 0 0 .534 9\"/>\r\n <path fill-rule=\"evenodd\" d=\"M8 3c-1.552 0-2.94.707-3.857 1.818a.5.5 0 1 1-.771-.636A6.002 6.002 0 0 1 13.917 7H12.9A5 5 0 0 0 8 3M3.1 9a5.002 5.002 0 0 0 8.757 2.182.5.5 0 1 1 .771.636A6.002 6.002 0 0 1 2.083 9z\"/>\r\n </svg>\r\n </div>\r\n }\r\n}\r\n", styles: [":host{display:flex;padding:0;margin:3px 0 0;min-width:24px}.spinner{margin-left:auto;width:20px;height:20px}.spinner svg{animation:spinnerRotation 1.5s linear infinite}@keyframes spinnerRotation{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }); }
6405
+ }
6406
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxIconRendererComponent, decorators: [{
6407
+ type: Component,
6408
+ args: [{ selector: 'atx-icon-renderer', standalone: true, imports: [], template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n@if (log) {\r\n @if (hasReponse) {\r\n <svg width=\"24\" height=\"24\" fill=\"currentColor\">\r\n @if (bodyType == 0) {\r\n <use href=\"#empty-icon\"/>\r\n } @else if (bodyType == 1) {\r\n <use href=\"#json-icon\"/>\r\n } @else if (bodyType == 2) {\r\n <use href=\"#text-icon\"/>\r\n } @else if (bodyType == 3) {\r\n <use href=\"#blob-icon\"/>\r\n } @else if (bodyType == 5) {\r\n <use href=\"#bin-icon\"/>\r\n }\r\n </svg>\r\n @if (isImported) {\r\n <svg width=\"24\" height=\"24\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path fill-rule=\"evenodd\" d=\"M3.5 6a.5.5 0 0 0-.5.5v8a.5.5 0 0 0 .5.5h9a.5.5 0 0 0 .5-.5v-8a.5.5 0 0 0-.5-.5h-2a.5.5 0 0 1 0-1h2A1.5 1.5 0 0 1 14 6.5v8a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 2 14.5v-8A1.5 1.5 0 0 1 3.5 5h2a.5.5 0 0 1 0 1z\"/>\r\n <path fill-rule=\"evenodd\" d=\"M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708z\"/>\r\n </svg>\r\n }\r\n } @else {\r\n <div class=\"spinner\">\r\n <svg width=\"20\" height=\"20\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M11.534 7h3.932a.25.25 0 0 1 .192.41l-1.966 2.36a.25.25 0 0 1-.384 0l-1.966-2.36a.25.25 0 0 1 .192-.41m-11 2h3.932a.25.25 0 0 0 .192-.41L2.692 6.23a.25.25 0 0 0-.384 0L.342 8.59A.25.25 0 0 0 .534 9\"/>\r\n <path fill-rule=\"evenodd\" d=\"M8 3c-1.552 0-2.94.707-3.857 1.818a.5.5 0 1 1-.771-.636A6.002 6.002 0 0 1 13.917 7H12.9A5 5 0 0 0 8 3M3.1 9a5.002 5.002 0 0 0 8.757 2.182.5.5 0 1 1 .771.636A6.002 6.002 0 0 1 2.083 9z\"/>\r\n </svg>\r\n </div>\r\n }\r\n}\r\n", styles: [":host{display:flex;padding:0;margin:3px 0 0;min-width:24px}.spinner{margin-left:auto;width:20px;height:20px}.spinner svg{animation:spinnerRotation 1.5s linear infinite}@keyframes spinnerRotation{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }]
6409
+ }], propDecorators: { data: [{
6410
+ type: Input
6411
+ }] } });
4393
6412
 
4394
6413
  /**
4395
- * A basic implementation of a HTML sanitization pipe.
6414
+ * @license
6415
+ * Copyright Pascal ECHEMANN. All Rights Reserved.
6416
+ *
6417
+ * Use of this source code is governed by an MIT-style license that can be found in
6418
+ * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license
4396
6419
  */
4397
- class SafeHtmlPipe {
4398
- /**
4399
- * @private
4400
- */
4401
- constructor(_sanitizer) {
4402
- this._sanitizer = _sanitizer;
6420
+ const TPL_DASH = "---";
6421
+ const PREFETCH = "prefetch";
6422
+ const MS_SUFIX = " ms";
6423
+ class AtxMonitoringConsoleComponent extends IdentifiableComponent {
6424
+ constructor(logger, _cdr, _subscribe, _ioSvc) {
6425
+ super();
6426
+ this.logger = logger;
6427
+ this._cdr = _cdr;
6428
+ this._subscribe = _subscribe;
6429
+ this._ioSvc = _ioSvc;
6430
+ this.selectedLog = null;
6431
+ this.cumulativeSize = 0;
6432
+ this.logs = [];
6433
+ const connector = new HttpMonitoringConsoleLogConnector();
6434
+ this.connector = connector;
6435
+ logger.setLogConnector(connector);
6436
+ this._subscribe.register(this, connector.change.subscribe((log) => this.addLog(log)));
4403
6437
  }
4404
- /**
4405
- * Transforms the HTML input string value into a `SafeHtml` instance and returns the result
4406
- * of the transformation.
4407
- *
4408
- * @param value The HTML input value to transform into a `SafeHtml` instance.
4409
- * @returns A `SafeHtml` instance based on the specified input value.
4410
- */
4411
- transform(value) {
4412
- return this._sanitizer.bypassSecurityTrustHtml(value);
6438
+ ngOnDestroy() {
6439
+ this._subscribe.clearAll(this);
4413
6440
  }
4414
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: SafeHtmlPipe, deps: [{ token: i1$1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe }); }
4415
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.0.3", ngImport: i0, type: SafeHtmlPipe, isStandalone: true, name: "safeHtml" }); }
6441
+ logSelect(log) {
6442
+ this.selectedLog = log;
6443
+ }
6444
+ getResourceName(log) {
6445
+ return UrlUtil.getResourceName(log);
6446
+ }
6447
+ getResourcePath(log) {
6448
+ return UrlUtil.getResourcePath(log);
6449
+ }
6450
+ getSize(log) {
6451
+ const response = log.metadata.response;
6452
+ if (response) {
6453
+ const size = SizeUtil.getSize(response.body);
6454
+ return SizeUtil.sizeToString(size);
6455
+ }
6456
+ return TPL_DASH;
6457
+ }
6458
+ getStatus(log) {
6459
+ const response = log.metadata.response;
6460
+ if (response)
6461
+ return response.status;
6462
+ return PREFETCH;
6463
+ }
6464
+ getTime(log) {
6465
+ const response = log.metadata.response;
6466
+ if (response)
6467
+ return log.metadata.requestMetadata.duration + MS_SUFIX;
6468
+ return TPL_DASH;
6469
+ }
6470
+ isError(log) {
6471
+ const response = log.metadata.response;
6472
+ if (response)
6473
+ return response.status >= 400;
6474
+ return false;
6475
+ }
6476
+ isImported(log) {
6477
+ return log.metadata.request?.context.get(ATX_IS_IMPORTED_LOG);
6478
+ }
6479
+ checkFilters(log) {
6480
+ return true;
6481
+ }
6482
+ userAction(action) {
6483
+ switch (action.type) {
6484
+ case AtxConsoleActionType.CLEAR_LOGS:
6485
+ this.clearLogs();
6486
+ break;
6487
+ case AtxConsoleActionType.EXPORT_LOGS:
6488
+ this.exportLogs();
6489
+ break;
6490
+ case AtxConsoleActionType.IMPORT_LOGS:
6491
+ this.importLogs();
6492
+ break;
6493
+ }
6494
+ }
6495
+ addLog(log) {
6496
+ if (log.level !== LogLevel.CONFIG) {
6497
+ const size = SizeUtil.getSize(log.metadata.response.body);
6498
+ const id = log.metadata.requestMetadata.id;
6499
+ this.cumulativeSize += size;
6500
+ const idx = this.logs.findIndex(prefetch => prefetch.metadata.requestMetadata.id === id);
6501
+ idx > -1 ? this.logs.splice(idx, 1, log) : this.logs.push(log);
6502
+ if (this.selectedLog?.metadata.requestMetadata.id === id)
6503
+ this.selectedLog = log;
6504
+ }
6505
+ else
6506
+ this.logs.push(log);
6507
+ this._cdr.detectChanges();
6508
+ }
6509
+ clearLogs() {
6510
+ this.logger.clearLogs();
6511
+ this.logSelect(null);
6512
+ this.cumulativeSize = this.logs.length = 0;
6513
+ }
6514
+ exportLogs() {
6515
+ this._ioSvc.exportFile(this.logs);
6516
+ }
6517
+ importLogs() {
6518
+ this._ioSvc.importFile();
6519
+ }
6520
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxMonitoringConsoleComponent, deps: [{ token: HttpMockLoggingService }, { token: i0.ChangeDetectorRef }, { token: SubscriptionService }, { token: AtxLogIoService }], target: i0.ɵɵFactoryTarget.Component }); }
6521
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.3", type: AtxMonitoringConsoleComponent, isStandalone: true, selector: "atx-http-monitoring-console", providers: [
6522
+ AtxLogIoService
6523
+ ], usesInheritance: true, ngImport: i0, template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n<atx-console-menu (action)=\"userAction($event)\"/>\r\n\r\n<div id=\"log-list-vieport\">\r\n <div class=\"request-list-wrapper\" [class.reduced-request-list]=\"selectedLog\">\r\n <table id=\"request-list\" >\r\n <thead>\r\n <tr>\r\n <th class=\"name-header\">\r\n Name\r\n <div role=\"button\" (click)=\"selectedLog = null\" title=\"Expand\" class=\"header-btn\">\r\n <svg width=\"20\" height=\"20\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n @if (selectedLog) {\r\n <path fill-rule=\"evenodd\" d=\"M6 8a.5.5 0 0 0 .5.5h5.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3a.5.5 0 0 0 0-.708l-3-3a.5.5 0 0 0-.708.708L12.293 7.5H6.5A.5.5 0 0 0 6 8m-2.5 7a.5.5 0 0 1-.5-.5v-13a.5.5 0 0 1 1 0v13a.5.5 0 0 1-.5.5\"/>\r\n }\r\n </svg>\r\n </div>\r\n </th>\r\n @if (!selectedLog) {\r\n <th>Status</th>\r\n <th>Size</th>\r\n <th>Time</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (log of logs; track log.metadata.requestMetadata.id) {\r\n @if (checkFilters(log)) {\r\n <tr [class.error-row]=\"isError(log)\" role=\"button\" (click)=\"logSelect(log)\"\r\n [class.selected-row]=\"selectedLog === log\">\r\n <td [title]=\"getResourcePath(log)\">\r\n <atx-icon-renderer [data]=\"log\"/>\r\n <div class=\"resource-cell\">\r\n {{ getResourceName(log) }}\r\n <br>\r\n {{ getResourcePath(log) }}\r\n </div>\r\n </td>\r\n @if (!selectedLog) {\r\n <td>{{ getStatus(log) }}</td>\r\n <td>{{ getSize(log) }}</td>\r\n <td>{{ getTime(log) }}</td>\r\n }\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n @if (selectedLog) {\r\n <div id=\"selected-log-viewport\">\r\n <atx-monitoring-console-details [log]=\"selectedLog\" (close)=\"logSelect(null)\"/>\r\n </div>\r\n }\r\n</div>\r\n\r\n<atx-console-footer [cumulativeSize]=\"cumulativeSize\" [numLogs]=\"logs.length\"/>\r\n\r\n<svg id=\"icon-collection\">\r\n <symbol id=\"json-icon\" viewBox=\"0 0 16 16\">\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n <path d=\"M8.646 6.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 9 8.646 7.354a.5.5 0 0 1 0-.708m-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 9l1.647-1.646a.5.5 0 0 0 0-.708\"/>\r\n </symbol>\r\n <symbol id=\"bin-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M5.526 13.09c.976 0 1.524-.79 1.524-2.205 0-1.412-.548-2.203-1.524-2.203-.978 0-1.526.79-1.526 2.203 0 1.415.548 2.206 1.526 2.206zm-.832-2.205c0-1.05.29-1.612.832-1.612.358 0 .607.247.733.721L4.7 11.137a7 7 0 0 1-.006-.252m.832 1.614c-.36 0-.606-.246-.732-.718l1.556-1.145q.005.12.005.249c0 1.052-.29 1.614-.829 1.614m5.329.501v-.595H9.73V8.772h-.69l-1.19.786v.688L8.986 9.5h.05v2.906h-1.18V13h3z\"/>\r\n <path d=\"M4 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zm0 1h8a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1\"/>\r\n </symbol>\r\n <symbol id=\"text-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M10.943 6H5.057L5 8h.5c.18-1.096.356-1.192 1.694-1.235l.293-.01v5.09c0 .47-.1.582-.898.655v.5H9.41v-.5c-.803-.073-.903-.184-.903-.654V6.755l.298.01c1.338.043 1.514.14 1.694 1.235h.5l-.057-2z\"/>\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n </symbol>\r\n <symbol id=\"empty-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n </symbol>\r\n <symbol id=\"blob-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M8.002 5.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0\"/>\r\n <path d=\"M12 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2M3 2a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v8l-2.083-2.083a.5.5 0 0 0-.76.063L8 11 5.835 9.7a.5.5 0 0 0-.611.076L3 12z\"/>\r\n </symbol>\r\n</svg>", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}:host{position:relative;padding:0;margin:0}#log-list-vieport{position:absolute;width:100%;display:flex;flex-direction:row;gap:6px;padding:6px;top:34px;bottom:34px}#icon-collection{visibility:hidden;width:0;height:0}.request-list-wrapper{height:100%;flex-grow:1;overflow:hidden auto;border:1px solid var(--border-color)}#request-list{-webkit-user-select:none;user-select:none;width:100%}#request-list tbody tr td:first-of-type{display:flex;gap:6px}#request-list svg{margin-top:2px}#request-list .name-header{display:flex;align-items:center}#request-list thead{position:sticky;top:0}#request-list .resource-cell{max-height:40px;overflow:hidden}#selected-log-viewport{height:100%;width:80%}atx-console-footer{position:absolute;width:100%;bottom:0}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"], dependencies: [{ kind: "component", type: AtxRequestDetailsComponent, selector: "atx-monitoring-console-details", inputs: ["log"], outputs: ["close"] }, { kind: "component", type: AtxConsoleFooterComponent, selector: "atx-console-footer", inputs: ["cumulativeSize", "numLogs"] }, { kind: "component", type: AtxConsoleMenuComponent, selector: "atx-console-menu", outputs: ["action"] }, { kind: "component", type: AtxIconRendererComponent, selector: "atx-icon-renderer", inputs: ["data"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4416
6524
  }
4417
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: SafeHtmlPipe, decorators: [{
4418
- type: Pipe,
4419
- args: [{
4420
- name: 'safeHtml',
4421
- standalone: true
4422
- }]
4423
- }], ctorParameters: () => [{ type: i1$1.DomSanitizer }] });
6525
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: AtxMonitoringConsoleComponent, decorators: [{
6526
+ type: Component,
6527
+ args: [{ selector: 'atx-http-monitoring-console', standalone: true, imports: [
6528
+ AtxRequestDetailsComponent,
6529
+ AtxConsoleFooterComponent,
6530
+ AtxConsoleMenuComponent,
6531
+ AtxIconRendererComponent
6532
+ ], providers: [
6533
+ AtxLogIoService
6534
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\r\n * LICENSE\r\n * Copyright Pascal ECHEMANN. All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\r\n-->\r\n\r\n<atx-console-menu (action)=\"userAction($event)\"/>\r\n\r\n<div id=\"log-list-vieport\">\r\n <div class=\"request-list-wrapper\" [class.reduced-request-list]=\"selectedLog\">\r\n <table id=\"request-list\" >\r\n <thead>\r\n <tr>\r\n <th class=\"name-header\">\r\n Name\r\n <div role=\"button\" (click)=\"selectedLog = null\" title=\"Expand\" class=\"header-btn\">\r\n <svg width=\"20\" height=\"20\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n @if (selectedLog) {\r\n <path fill-rule=\"evenodd\" d=\"M6 8a.5.5 0 0 0 .5.5h5.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3a.5.5 0 0 0 0-.708l-3-3a.5.5 0 0 0-.708.708L12.293 7.5H6.5A.5.5 0 0 0 6 8m-2.5 7a.5.5 0 0 1-.5-.5v-13a.5.5 0 0 1 1 0v13a.5.5 0 0 1-.5.5\"/>\r\n }\r\n </svg>\r\n </div>\r\n </th>\r\n @if (!selectedLog) {\r\n <th>Status</th>\r\n <th>Size</th>\r\n <th>Time</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (log of logs; track log.metadata.requestMetadata.id) {\r\n @if (checkFilters(log)) {\r\n <tr [class.error-row]=\"isError(log)\" role=\"button\" (click)=\"logSelect(log)\"\r\n [class.selected-row]=\"selectedLog === log\">\r\n <td [title]=\"getResourcePath(log)\">\r\n <atx-icon-renderer [data]=\"log\"/>\r\n <div class=\"resource-cell\">\r\n {{ getResourceName(log) }}\r\n <br>\r\n {{ getResourcePath(log) }}\r\n </div>\r\n </td>\r\n @if (!selectedLog) {\r\n <td>{{ getStatus(log) }}</td>\r\n <td>{{ getSize(log) }}</td>\r\n <td>{{ getTime(log) }}</td>\r\n }\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n @if (selectedLog) {\r\n <div id=\"selected-log-viewport\">\r\n <atx-monitoring-console-details [log]=\"selectedLog\" (close)=\"logSelect(null)\"/>\r\n </div>\r\n }\r\n</div>\r\n\r\n<atx-console-footer [cumulativeSize]=\"cumulativeSize\" [numLogs]=\"logs.length\"/>\r\n\r\n<svg id=\"icon-collection\">\r\n <symbol id=\"json-icon\" viewBox=\"0 0 16 16\">\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n <path d=\"M8.646 6.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 9 8.646 7.354a.5.5 0 0 1 0-.708m-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 9l1.647-1.646a.5.5 0 0 0 0-.708\"/>\r\n </symbol>\r\n <symbol id=\"bin-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M5.526 13.09c.976 0 1.524-.79 1.524-2.205 0-1.412-.548-2.203-1.524-2.203-.978 0-1.526.79-1.526 2.203 0 1.415.548 2.206 1.526 2.206zm-.832-2.205c0-1.05.29-1.612.832-1.612.358 0 .607.247.733.721L4.7 11.137a7 7 0 0 1-.006-.252m.832 1.614c-.36 0-.606-.246-.732-.718l1.556-1.145q.005.12.005.249c0 1.052-.29 1.614-.829 1.614m5.329.501v-.595H9.73V8.772h-.69l-1.19.786v.688L8.986 9.5h.05v2.906h-1.18V13h3z\"/>\r\n <path d=\"M4 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zm0 1h8a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1\"/>\r\n </symbol>\r\n <symbol id=\"text-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M10.943 6H5.057L5 8h.5c.18-1.096.356-1.192 1.694-1.235l.293-.01v5.09c0 .47-.1.582-.898.655v.5H9.41v-.5c-.803-.073-.903-.184-.903-.654V6.755l.298.01c1.338.043 1.514.14 1.694 1.235h.5l-.057-2z\"/>\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n </symbol>\r\n <symbol id=\"empty-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z\"/>\r\n </symbol>\r\n <symbol id=\"blob-icon\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M8.002 5.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0\"/>\r\n <path d=\"M12 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2M3 2a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v8l-2.083-2.083a.5.5 0 0 0-.76.063L8 11 5.835 9.7a.5.5 0 0 0-.611.076L3 12z\"/>\r\n </symbol>\r\n</svg>", styles: [":host{font-family:Verdana,Geneva,Tahoma,sans-serif;font-size:13px;--border-color: lightblue;--background-color: aliceblue;--selected-color: #d9eeff;--selected-error-color: lavenderblush;--light-gray: whitesmoke;--dark-gray: gainsboro;color:#000;background-color:#fff;display:block}menu{padding:0;margin:0;display:flex;align-items:center;gap:6px;list-style:none}table{border-collapse:collapse}th{padding:0 0 0 6px;background-color:var(--background-color);border-bottom:1px solid var(--border-color);position:sticky;top:0}th:not(:last-child){border-right:1px solid var(--border-color)}td{padding:2px 6px;vertical-align:top}tr:nth-child(2n):not(.selected-row){background-color:var(--background-color)}.error-row{color:red}.selected-row{background-color:var(--selected-color)}.error-row.selected-row{background-color:var(--selected-error-color)}tr:hover{background-color:var(--light-gray)}.header-btn{padding:4px;margin-left:auto}.header-btn:hover{background-color:var(--selected-color)}.menu-separator{width:0;height:16px;border-right:2px solid var(--dark-gray)}.content{padding:4px 6px}.center-content{display:flex;justify-content:center}:host{position:relative;padding:0;margin:0}#log-list-vieport{position:absolute;width:100%;display:flex;flex-direction:row;gap:6px;padding:6px;top:34px;bottom:34px}#icon-collection{visibility:hidden;width:0;height:0}.request-list-wrapper{height:100%;flex-grow:1;overflow:hidden auto;border:1px solid var(--border-color)}#request-list{-webkit-user-select:none;user-select:none;width:100%}#request-list tbody tr td:first-of-type{display:flex;gap:6px}#request-list svg{margin-top:2px}#request-list .name-header{display:flex;align-items:center}#request-list thead{position:sticky;top:0}#request-list .resource-cell{max-height:40px;overflow:hidden}#selected-log-viewport{height:100%;width:80%}atx-console-footer{position:absolute;width:100%;bottom:0}\n/**\n * @license\n * Copyright Pascal ECHEMANN. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be found in\n * the LICENSE file at https://pascalechemann.com/angular-toolbox/resources/license\n */\n"] }]
6535
+ }], ctorParameters: () => [{ type: HttpMockLoggingService }, { type: i0.ChangeDetectorRef }, { type: SubscriptionService }, { type: AtxLogIoService }] });
4424
6536
 
4425
6537
  /**
4426
6538
  * @license
@@ -4437,5 +6549,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImpor
4437
6549
  * Generated bundle index. Do not edit.
4438
6550
  */
4439
6551
 
4440
- export { APP_PRIDGE_REF, AbstractSubscriptionManager, AbstractVersionManager, AnchorLinklDirective, AngularToolboxLogoComponent, AngularToolboxModule, AngularToolboxVersionService, AppBridgeError, AppBrigeService, ArrayList, ArrayListEvent, ArrayListEventType, BIGINT, BOOLEAN, BUTTON_ROLE, ButtonRoleDirective, CSS_PROP, ContentRendererDirective, DARK_MODE_CONFIG, DarkModeService, EMPTY_STRING, FUNCTION, FetchClientBuilder, FetchClientResponseType, HTTP_MOCKING_FRAMEWORK_CONFIG, HTTP_MOCK_SERVICE, HttpHeadersMockBuilder, HttpMock, HttpMockProductionPolicy, HttpMockService, HttpMockServiceError, HttpResponseMockBuilder, IdentifiableComponent, IntegrityError, LINK_ROLE, NUMBER, NavigateToUrlDirective, OBJECT, STORAGE_KEY, STRING, SYMBOL, SafeHtmlPipe, ScrollService, SubscriptionError, SubscriptionService, UNDEFINED, Uuid, VERSION_CONFIG, VersionService, httpHeadersMock, httpMockFactory, httpResponseMock };
6552
+ export { APP_PRIDGE_REF, AbstractLogger, AbstractSubscriptionManager, AbstractVersionManager, AnchorLinklDirective, AngularToolboxLogoComponent, AngularToolboxModule, AngularToolboxVersionService, AppBridgeError, AppBrigeService, ArrayList, ArrayListEvent, ArrayListEventType, AtxMonitoringConsoleComponent, BIGINT, BOOLEAN, BUTTON_ROLE, ButtonRoleDirective, CSS_PROP, ConsoleLogConnector, ContentRendererDirective, DARK_MODE_CONFIG, DEFAULT_LOG_CONNECTOR, DarkModeService, DefaultLogConnector, EMPTY_STRING, FUNCTION, FetchClient, FetchClientBuilder, FetchClientResponseType, HTTP_MOCKING_FRAMEWORK_CONFIG, HTTP_MOCK_MAX_DELAY, HTTP_MOCK_SERVICE, HtmlLogConnector, HttpHeadersMockBuilder, HttpMock, HttpMockLoggingService, HttpMockProductionPolicy, HttpMockService, HttpMockServiceError, HttpResponseMockBuilder, IdentifiableComponent, IntegrityError, LINK_ROLE, LOG_CONFIG_STRING, LOG_ERROR_STRING, LOG_INFO_STRING, LOG_WARNING_STRING, LogBuilder, LogImpl, LogLevel, LogUtil, LoggerService, NUMBER, NavigateToUrlDirective, OBJECT, STORAGE_KEY, STRING, SYMBOL, SafeHtmlPipe, ScrollService, SubscriptionError, SubscriptionService, UNDEFINED, Uuid, VERSION_CONFIG, VersionService, httpHeadersMock, httpMockFactory, httpResponseMock };
4441
6553
  //# sourceMappingURL=angular-toolbox.mjs.map