angular-toolbox 0.11.3 → 0.12.0

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