@geoit/ui 0.0.2 → 0.0.5

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 (258) hide show
  1. package/AGENTS.md +12 -8
  2. package/README.md +140 -17
  3. package/ai/AGENTS.md +43 -32
  4. package/ai/README.md +36 -2
  5. package/ai/catalog.json +5585 -437
  6. package/ai/components/geo-alert.md +75 -21
  7. package/ai/components/geo-back-button.md +64 -18
  8. package/ai/components/geo-breadcrumb.md +71 -12
  9. package/ai/components/geo-button.md +90 -27
  10. package/ai/components/geo-chart.md +103 -0
  11. package/ai/components/geo-checkbox.md +67 -20
  12. package/ai/components/geo-column-picker.md +91 -18
  13. package/ai/components/geo-confirm-modal.md +92 -27
  14. package/ai/components/geo-dashboard.md +91 -0
  15. package/ai/components/geo-date-picker.md +105 -29
  16. package/ai/components/geo-date-range-picker.md +101 -28
  17. package/ai/components/geo-empty-state.md +75 -0
  18. package/ai/components/geo-feedback-form.md +97 -0
  19. package/ai/components/geo-file-picker.md +99 -26
  20. package/ai/components/geo-forgot-password.md +78 -0
  21. package/ai/components/geo-form-modal.md +111 -44
  22. package/ai/components/geo-icon.md +70 -16
  23. package/ai/components/geo-input.md +94 -29
  24. package/ai/components/geo-layout-footer.md +70 -0
  25. package/ai/components/geo-layout-header-actions.md +82 -0
  26. package/ai/components/geo-layout-header.md +89 -0
  27. package/ai/components/geo-layout-sidebar.md +86 -0
  28. package/ai/components/geo-layout.md +155 -0
  29. package/ai/components/geo-list-page.md +72 -0
  30. package/ai/components/geo-login.md +94 -0
  31. package/ai/components/geo-map-admin-filter.md +80 -0
  32. package/ai/components/geo-map-basemap-switcher.md +75 -0
  33. package/ai/components/geo-map-help.md +72 -0
  34. package/ai/components/geo-map-layer-card.md +73 -0
  35. package/ai/components/geo-map-layer-panel.md +75 -0
  36. package/ai/components/geo-map-layers-drawer.md +78 -0
  37. package/ai/components/geo-map-legend.md +74 -0
  38. package/ai/components/geo-map-locate.md +75 -0
  39. package/ai/components/geo-map-location-chip.md +71 -0
  40. package/ai/components/geo-map-measure.md +74 -0
  41. package/ai/components/geo-map-opacity.md +75 -0
  42. package/ai/components/geo-map-parcel-popup.md +79 -0
  43. package/ai/components/geo-map-search.md +83 -0
  44. package/ai/components/geo-map-shell.md +110 -0
  45. package/ai/components/geo-map-snapshot.md +75 -0
  46. package/ai/components/geo-map-swipe.md +73 -0
  47. package/ai/components/geo-map-toolbar.md +76 -0
  48. package/ai/components/geo-map-zoom.md +74 -0
  49. package/ai/components/geo-map.md +205 -0
  50. package/ai/components/geo-overlap-result.md +88 -0
  51. package/ai/components/geo-page-header.md +72 -0
  52. package/ai/components/geo-page-title.md +62 -16
  53. package/ai/components/geo-pagination.md +76 -24
  54. package/ai/components/geo-radio.md +110 -27
  55. package/ai/components/geo-row-actions.md +87 -19
  56. package/ai/components/geo-select.md +108 -28
  57. package/ai/components/geo-slider.md +70 -21
  58. package/ai/components/geo-stat-card.md +98 -0
  59. package/ai/components/geo-status-tag.md +67 -15
  60. package/ai/components/geo-step-form-layout.md +121 -38
  61. package/ai/components/geo-stepper.md +81 -19
  62. package/ai/components/geo-table-filter.md +90 -29
  63. package/ai/components/geo-table-pagination.md +70 -23
  64. package/ai/components/geo-table-toolbar.md +84 -29
  65. package/ai/components/geo-table.md +191 -59
  66. package/ai/components/geo-tabs.md +99 -27
  67. package/ai/components/geo-textarea.md +84 -23
  68. package/ai/components/geo-toast.md +138 -27
  69. package/ai/components/geo-tree.md +94 -22
  70. package/ai/components/geo-typography.md +70 -19
  71. package/ai/components/geo-upload.md +109 -39
  72. package/ai/mockup.html +1194 -0
  73. package/ai/recipes.md +132 -47
  74. package/esm2022/lib/figma/geo-alert/geo-alert.component.mjs +19 -36
  75. package/esm2022/lib/figma/geo-back-button/geo-back-button.component.mjs +14 -24
  76. package/esm2022/lib/figma/geo-breadcrumb/geo-breadcrumb.component.mjs +8 -11
  77. package/esm2022/lib/figma/geo-button/geo-button.component.mjs +30 -59
  78. package/esm2022/lib/figma/geo-chart/geo-chart.component.mjs +88 -0
  79. package/esm2022/lib/figma/geo-chart/geo-chart.types.mjs +2 -0
  80. package/esm2022/lib/figma/geo-checkbox/geo-checkbox.component.mjs +11 -22
  81. package/esm2022/lib/figma/geo-confirm-modal/geo-confirm-modal.component.mjs +22 -54
  82. package/esm2022/lib/figma/geo-dashboard/geo-dashboard.component.mjs +49 -0
  83. package/esm2022/lib/figma/geo-dashboard/geo-dashboard.types.mjs +2 -0
  84. package/esm2022/lib/figma/geo-date-picker/geo-date-picker.component.mjs +48 -78
  85. package/esm2022/lib/figma/geo-date-range-picker/geo-date-range-picker.component.mjs +47 -75
  86. package/esm2022/lib/figma/geo-empty-state/geo-empty-state.component.mjs +25 -0
  87. package/esm2022/lib/figma/geo-feedback-form/geo-feedback-form.component.mjs +75 -0
  88. package/esm2022/lib/figma/geo-feedback-form/geo-feedback-form.types.mjs +2 -0
  89. package/esm2022/lib/figma/geo-file-picker/geo-file-picker.component.mjs +59 -81
  90. package/esm2022/lib/figma/geo-forgot-password/geo-forgot-password.component.mjs +51 -0
  91. package/esm2022/lib/figma/geo-form-modal/geo-form-modal.component.mjs +45 -112
  92. package/esm2022/lib/figma/geo-icon/geo-icon.component.mjs +22 -32
  93. package/esm2022/lib/figma/geo-input/geo-input.component.mjs +41 -70
  94. package/esm2022/lib/figma/geo-layout/footer/geo-layout-footer.component.mjs +18 -0
  95. package/esm2022/lib/figma/geo-layout/geo-layout-actions.directive.mjs +15 -0
  96. package/esm2022/lib/figma/geo-layout/geo-layout.component.mjs +79 -0
  97. package/esm2022/lib/figma/geo-layout/geo-layout.types.mjs +42 -0
  98. package/esm2022/lib/figma/geo-layout/header/geo-layout-header.component.mjs +60 -0
  99. package/esm2022/lib/figma/geo-layout/header-actions/geo-layout-header-actions.component.mjs +70 -0
  100. package/esm2022/lib/figma/geo-layout/sidebar/geo-layout-sidebar.component.mjs +90 -0
  101. package/esm2022/lib/figma/geo-list-page/geo-list-page.component.mjs +22 -0
  102. package/esm2022/lib/figma/geo-login/geo-login.component.mjs +58 -0
  103. package/esm2022/lib/figma/geo-login/geo-login.types.mjs +2 -0
  104. package/esm2022/lib/figma/geo-map/chrome/geo-map-admin-filter/geo-map-admin-filter.component.mjs +52 -0
  105. package/esm2022/lib/figma/geo-map/chrome/geo-map-basemap-switcher/geo-map-basemap-switcher.component.mjs +61 -0
  106. package/esm2022/lib/figma/geo-map/chrome/geo-map-help/geo-map-help.component.mjs +26 -0
  107. package/esm2022/lib/figma/geo-map/chrome/geo-map-layer-card/geo-map-layer-card.component.mjs +24 -0
  108. package/esm2022/lib/figma/geo-map/chrome/geo-map-layer-panel/geo-map-layer-panel.component.mjs +146 -0
  109. package/esm2022/lib/figma/geo-map/chrome/geo-map-layers-drawer/geo-map-layers-drawer.component.mjs +37 -0
  110. package/esm2022/lib/figma/geo-map/chrome/geo-map-legend/geo-map-legend.component.mjs +30 -0
  111. package/esm2022/lib/figma/geo-map/chrome/geo-map-locate/geo-map-locate.component.mjs +72 -0
  112. package/esm2022/lib/figma/geo-map/chrome/geo-map-location-chip/geo-map-location-chip.component.mjs +21 -0
  113. package/esm2022/lib/figma/geo-map/chrome/geo-map-measure/geo-map-measure.component.mjs +375 -0
  114. package/esm2022/lib/figma/geo-map/chrome/geo-map-opacity/geo-map-opacity.component.mjs +94 -0
  115. package/esm2022/lib/figma/geo-map/chrome/geo-map-parcel-popup/geo-map-parcel-popup.component.mjs +136 -0
  116. package/esm2022/lib/figma/geo-map/chrome/geo-map-search/geo-map-search.component.mjs +182 -0
  117. package/esm2022/lib/figma/geo-map/chrome/geo-map-shell/geo-map-shell.component.mjs +577 -0
  118. package/esm2022/lib/figma/geo-map/chrome/geo-map-snapshot/geo-map-snapshot.component.mjs +93 -0
  119. package/esm2022/lib/figma/geo-map/chrome/geo-map-swipe/geo-map-swipe.component.mjs +129 -0
  120. package/esm2022/lib/figma/geo-map/chrome/geo-map-toolbar/geo-map-toolbar.component.mjs +64 -0
  121. package/esm2022/lib/figma/geo-map/chrome/geo-map-zoom/geo-map-zoom.component.mjs +295 -0
  122. package/esm2022/lib/figma/geo-map/geo-map-toolbar.icons.mjs +18 -0
  123. package/esm2022/lib/figma/geo-map/geo-map.component.mjs +144 -0
  124. package/esm2022/lib/figma/geo-map/geo-map.constants.mjs +497 -0
  125. package/esm2022/lib/figma/geo-map/geo-map.controller.mjs +71 -0
  126. package/esm2022/lib/figma/geo-map/geo-map.types.mjs +2 -0
  127. package/esm2022/lib/figma/geo-map/services/geo-map-layer.service.mjs +368 -0
  128. package/esm2022/lib/figma/geo-map/services/geo-map-projection.service.mjs +110 -0
  129. package/esm2022/lib/figma/geo-map/services/geo-map.service.mjs +540 -0
  130. package/esm2022/lib/figma/geo-map/utils/geo-map-fullscreen-overlay.util.mjs +47 -0
  131. package/esm2022/lib/figma/geo-map/utils/geo-map-interactions.util.mjs +30 -0
  132. package/esm2022/lib/figma/geo-overlap-result/geo-overlap-result.component.mjs +25 -0
  133. package/esm2022/lib/figma/geo-overlap-result/geo-overlap-result.types.mjs +2 -0
  134. package/esm2022/lib/figma/geo-page-header/geo-page-header.component.mjs +23 -0
  135. package/esm2022/lib/figma/geo-page-title/geo-page-title.component.mjs +20 -35
  136. package/esm2022/lib/figma/geo-pagination/geo-pagination.component.mjs +13 -43
  137. package/esm2022/lib/figma/geo-radio/geo-radio.component.mjs +32 -52
  138. package/esm2022/lib/figma/geo-select/geo-select.component.mjs +46 -72
  139. package/esm2022/lib/figma/geo-slider/geo-slider.component.mjs +12 -28
  140. package/esm2022/lib/figma/geo-stat-card/geo-stat-card.component.mjs +163 -0
  141. package/esm2022/lib/figma/geo-stat-card/geo-stat-card.types.mjs +2 -0
  142. package/esm2022/lib/figma/geo-status-tag/geo-status-tag.component.mjs +23 -27
  143. package/esm2022/lib/figma/geo-step-form-layout/geo-step-form-layout.component.mjs +39 -96
  144. package/esm2022/lib/figma/geo-stepper/geo-stepper.component.mjs +18 -33
  145. package/esm2022/lib/figma/geo-table/geo-column-picker/geo-column-picker.component.mjs +14 -24
  146. package/esm2022/lib/figma/geo-table/geo-row-actions/geo-row-actions.component.mjs +18 -36
  147. package/esm2022/lib/figma/geo-table/geo-table-filter/geo-table-filter.component.mjs +41 -98
  148. package/esm2022/lib/figma/geo-table/geo-table-pagination/geo-table-pagination.component.mjs +40 -73
  149. package/esm2022/lib/figma/geo-table/geo-table-toolbar/geo-table-toolbar.component.mjs +26 -56
  150. package/esm2022/lib/figma/geo-table/geo-table.component.mjs +110 -210
  151. package/esm2022/lib/figma/geo-tabs/geo-tabs.component.mjs +33 -63
  152. package/esm2022/lib/figma/geo-textarea/geo-textarea.component.mjs +28 -44
  153. package/esm2022/lib/figma/geo-toast/geo-toast.component.mjs +18 -39
  154. package/esm2022/lib/figma/geo-tree/geo-tree.component.mjs +12 -40
  155. package/esm2022/lib/figma/geo-typography/geo-typography.component.mjs +49 -64
  156. package/esm2022/lib/figma/geo-upload/geo-upload.component.mjs +50 -101
  157. package/esm2022/lib/figma/index.mjs +50 -1
  158. package/esm2022/lib/styles/tokens.mjs +56 -24
  159. package/fesm2022/geoit-ui.mjs +5981 -1825
  160. package/fesm2022/geoit-ui.mjs.map +1 -1
  161. package/lib/figma/geo-alert/geo-alert.component.d.ts +10 -11
  162. package/lib/figma/geo-back-button/geo-back-button.component.d.ts +6 -7
  163. package/lib/figma/geo-breadcrumb/geo-breadcrumb.component.d.ts +2 -2
  164. package/lib/figma/geo-button/geo-button.component.d.ts +21 -17
  165. package/lib/figma/geo-chart/geo-chart.component.d.ts +40 -0
  166. package/lib/figma/geo-chart/geo-chart.types.d.ts +13 -0
  167. package/lib/figma/geo-checkbox/geo-checkbox.component.d.ts +6 -7
  168. package/lib/figma/geo-confirm-modal/geo-confirm-modal.component.d.ts +15 -17
  169. package/lib/figma/geo-dashboard/geo-dashboard.component.d.ts +29 -0
  170. package/lib/figma/geo-dashboard/geo-dashboard.types.d.ts +7 -0
  171. package/lib/figma/geo-date-picker/geo-date-picker.component.d.ts +26 -21
  172. package/lib/figma/geo-date-range-picker/geo-date-range-picker.component.d.ts +25 -20
  173. package/lib/figma/geo-empty-state/geo-empty-state.component.d.ts +17 -0
  174. package/lib/figma/geo-feedback-form/geo-feedback-form.component.d.ts +36 -0
  175. package/lib/figma/geo-feedback-form/geo-feedback-form.types.d.ts +8 -0
  176. package/lib/figma/geo-file-picker/geo-file-picker.component.d.ts +23 -20
  177. package/lib/figma/geo-forgot-password/geo-forgot-password.component.d.ts +24 -0
  178. package/lib/figma/geo-form-modal/geo-form-modal.component.d.ts +33 -35
  179. package/lib/figma/geo-icon/geo-icon.component.d.ts +7 -7
  180. package/lib/figma/geo-input/geo-input.component.d.ts +23 -21
  181. package/lib/figma/geo-layout/footer/geo-layout-footer.component.d.ts +10 -0
  182. package/lib/figma/geo-layout/geo-layout-actions.directive.d.ts +6 -0
  183. package/lib/figma/geo-layout/geo-layout.component.d.ts +48 -0
  184. package/lib/figma/geo-layout/geo-layout.types.d.ts +44 -0
  185. package/lib/figma/geo-layout/header/geo-layout-header.component.d.ts +31 -0
  186. package/lib/figma/geo-layout/header-actions/geo-layout-header-actions.component.d.ts +32 -0
  187. package/lib/figma/geo-layout/sidebar/geo-layout-sidebar.component.d.ts +34 -0
  188. package/lib/figma/geo-list-page/geo-list-page.component.d.ts +16 -0
  189. package/lib/figma/geo-login/geo-login.component.d.ts +27 -0
  190. package/lib/figma/geo-login/geo-login.types.d.ts +6 -0
  191. package/lib/figma/geo-map/chrome/geo-map-admin-filter/geo-map-admin-filter.component.d.ts +28 -0
  192. package/lib/figma/geo-map/chrome/geo-map-basemap-switcher/geo-map-basemap-switcher.component.d.ts +26 -0
  193. package/lib/figma/geo-map/chrome/geo-map-help/geo-map-help.component.d.ts +20 -0
  194. package/lib/figma/geo-map/chrome/geo-map-layer-card/geo-map-layer-card.component.d.ts +15 -0
  195. package/lib/figma/geo-map/chrome/geo-map-layer-panel/geo-map-layer-panel.component.d.ts +40 -0
  196. package/lib/figma/geo-map/chrome/geo-map-layers-drawer/geo-map-layers-drawer.component.d.ts +25 -0
  197. package/lib/figma/geo-map/chrome/geo-map-legend/geo-map-legend.component.d.ts +18 -0
  198. package/lib/figma/geo-map/chrome/geo-map-locate/geo-map-locate.component.d.ts +24 -0
  199. package/lib/figma/geo-map/chrome/geo-map-location-chip/geo-map-location-chip.component.d.ts +14 -0
  200. package/lib/figma/geo-map/chrome/geo-map-measure/geo-map-measure.component.d.ts +49 -0
  201. package/lib/figma/geo-map/chrome/geo-map-opacity/geo-map-opacity.component.d.ts +30 -0
  202. package/lib/figma/geo-map/chrome/geo-map-parcel-popup/geo-map-parcel-popup.component.d.ts +44 -0
  203. package/lib/figma/geo-map/chrome/geo-map-search/geo-map-search.component.d.ts +56 -0
  204. package/lib/figma/geo-map/chrome/geo-map-shell/geo-map-shell.component.d.ts +103 -0
  205. package/lib/figma/geo-map/chrome/geo-map-snapshot/geo-map-snapshot.component.d.ts +21 -0
  206. package/lib/figma/geo-map/chrome/geo-map-swipe/geo-map-swipe.component.d.ts +33 -0
  207. package/lib/figma/geo-map/chrome/geo-map-toolbar/geo-map-toolbar.component.d.ts +30 -0
  208. package/lib/figma/geo-map/chrome/geo-map-zoom/geo-map-zoom.component.d.ts +67 -0
  209. package/lib/figma/geo-map/geo-map-toolbar.icons.d.ts +17 -0
  210. package/lib/figma/geo-map/geo-map.component.d.ts +53 -0
  211. package/lib/figma/geo-map/geo-map.constants.d.ts +73 -0
  212. package/lib/figma/geo-map/geo-map.controller.d.ts +49 -0
  213. package/lib/figma/geo-map/geo-map.types.d.ts +224 -0
  214. package/lib/figma/geo-map/services/geo-map-layer.service.d.ts +42 -0
  215. package/lib/figma/geo-map/services/geo-map-projection.service.d.ts +32 -0
  216. package/lib/figma/geo-map/services/geo-map.service.d.ts +99 -0
  217. package/lib/figma/geo-map/utils/geo-map-fullscreen-overlay.util.d.ts +13 -0
  218. package/lib/figma/geo-map/utils/geo-map-interactions.util.d.ts +9 -0
  219. package/lib/figma/geo-overlap-result/geo-overlap-result.component.d.ts +18 -0
  220. package/lib/figma/geo-overlap-result/geo-overlap-result.types.d.ts +7 -0
  221. package/lib/figma/geo-page-header/geo-page-header.component.d.ts +16 -0
  222. package/lib/figma/geo-page-title/geo-page-title.component.d.ts +9 -9
  223. package/lib/figma/geo-pagination/geo-pagination.component.d.ts +9 -14
  224. package/lib/figma/geo-radio/geo-radio.component.d.ts +17 -15
  225. package/lib/figma/geo-select/geo-select.component.d.ts +24 -19
  226. package/lib/figma/geo-slider/geo-slider.component.d.ts +7 -9
  227. package/lib/figma/geo-stat-card/geo-stat-card.component.d.ts +50 -0
  228. package/lib/figma/geo-stat-card/geo-stat-card.types.d.ts +11 -0
  229. package/lib/figma/geo-status-tag/geo-status-tag.component.d.ts +7 -7
  230. package/lib/figma/geo-step-form-layout/geo-step-form-layout.component.d.ts +27 -29
  231. package/lib/figma/geo-stepper/geo-stepper.component.d.ts +6 -8
  232. package/lib/figma/geo-table/geo-column-picker/geo-column-picker.component.d.ts +6 -7
  233. package/lib/figma/geo-table/geo-row-actions/geo-row-actions.component.d.ts +11 -12
  234. package/lib/figma/geo-table/geo-table-filter/geo-table-filter.component.d.ts +21 -28
  235. package/lib/figma/geo-table/geo-table-pagination/geo-table-pagination.component.d.ts +17 -20
  236. package/lib/figma/geo-table/geo-table-toolbar/geo-table-toolbar.component.d.ts +17 -18
  237. package/lib/figma/geo-table/geo-table.component.d.ts +58 -62
  238. package/lib/figma/geo-tabs/geo-tabs.component.d.ts +14 -17
  239. package/lib/figma/geo-textarea/geo-textarea.component.d.ts +15 -13
  240. package/lib/figma/geo-toast/geo-toast.component.d.ts +11 -12
  241. package/lib/figma/geo-tree/geo-tree.component.d.ts +8 -13
  242. package/lib/figma/geo-typography/geo-typography.component.d.ts +13 -13
  243. package/lib/figma/geo-upload/geo-upload.component.d.ts +26 -28
  244. package/lib/figma/index.d.ts +49 -0
  245. package/lib/styles/tokens.d.ts +56 -23
  246. package/package.json +4 -2
  247. package/src/lib/figma/geo-map/assets/toolbar/fullscreen.svg +8 -0
  248. package/src/lib/figma/geo-map/assets/toolbar/home.svg +3 -0
  249. package/src/lib/figma/geo-map/assets/toolbar/layers.svg +3 -0
  250. package/src/lib/figma/geo-map/assets/toolbar/measure-area.svg +12 -0
  251. package/src/lib/figma/geo-map/assets/toolbar/measure-distance.svg +5 -0
  252. package/src/lib/figma/geo-map/assets/toolbar/pan.svg +13 -0
  253. package/src/lib/figma/geo-map/assets/toolbar/search.svg +3 -0
  254. package/src/lib/figma/geo-map/assets/toolbar/zoom-in.svg +3 -0
  255. package/src/lib/figma/geo-map/assets/toolbar/zoom-out.svg +5 -0
  256. package/src/lib/styles/design-tokens.scss +108 -35
  257. package/src/lib/styles/scrollbar.scss +2 -2
  258. package/src/lib/styles/theme.scss +1 -1
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VvLW1hcC50eXBlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2dlby11aS9zcmMvbGliL2ZpZ21hL2dlby1tYXAvZ2VvLW1hcC50eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgRmVhdHVyZSBmcm9tICdvbC9GZWF0dXJlJztcbmltcG9ydCB0eXBlIEdlb21ldHJ5IGZyb20gJ29sL2dlb20vR2VvbWV0cnknO1xuXG4vKiogU3VwcG9ydGVkIG1hcCBsYXllciBzb3VyY2Uga2luZHMuICovXG5leHBvcnQgdHlwZSBHZW9NYXBMYXllclR5cGUgPVxuICB8ICdvc20nXG4gIHwgJ3h5eidcbiAgfCAnd21zJ1xuICB8ICd3bXRzJ1xuICB8ICd2ZWN0b3InXG4gIHwgJ2dlb2pzb24nO1xuXG4vKiogTGF5ZXIgbG9hZCBsaWZlY3ljbGUgZm9yIHBhbmVsIC8gY2hyb21lLiAqL1xuZXhwb3J0IHR5cGUgR2VvTWFwTGF5ZXJTdGF0dXMgPSAnaWRsZScgfCAnbG9hZGluZycgfCAncmVhZHknIHwgJ2Vycm9yJztcblxuZXhwb3J0IGludGVyZmFjZSBQcm9qZWN0aW9uQ29uZmlnIHtcbiAgY29kZTogc3RyaW5nO1xuICAvKiogRnVsbCBwcm9qNCBkZWZpbml0aW9uIHN0cmluZy4gTXVzdCBiZSBzdXBwbGllZCBieSBlbnYvQVBJIOKAlCBuZXZlciBpbnZlbnQgVk4tMjAwMCBwYXJhbXMuICovXG4gIGRlZmluaXRpb246IHN0cmluZztcbiAgZXh0ZW50PzogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG4gIHVuaXRzPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEdlb01hcExheWVyQmFzZSB7XG4gIGlkOiBzdHJpbmc7XG4gIHRpdGxlOiBzdHJpbmc7XG4gIHZpc2libGU/OiBib29sZWFuO1xuICAvKiogMOKAkzEgKi9cbiAgb3BhY2l0eT86IG51bWJlcjtcbiAgekluZGV4PzogbnVtYmVyO1xuICBtaW5ab29tPzogbnVtYmVyO1xuICBtYXhab29tPzogbnVtYmVyO1xuICAvKiogVHJlYXQgYXMgYmFzZW1hcCAob25seSBvbmUgYWN0aXZlIGF0IGEgdGltZSkuICovXG4gIGJhc2VtYXA/OiBib29sZWFuO1xuICAvKiogR3JvdXAga2V5IGZvciBsYXllciBwYW5lbCBzZWN0aW9ucyAoYGJhc2UtbWFwYCwgYHFoc2RkYCwg4oCmKS4gKi9cbiAgZ3JvdXA/OiBzdHJpbmc7XG4gIC8qKiBEaXNwbGF5IHRpdGxlIGZvciB0aGUgZ3JvdXAgYWNjb3JkaW9uIChmYWxscyBiYWNrIHRvIGdyb3VwIGtleSkuICovXG4gIGdyb3VwTGFiZWw/OiBzdHJpbmc7XG4gIC8qKiBTZWxlY3Rpb24gVVggd2l0aGluIHRoZSBncm91cDogcmFkaW8gKGBzaW5nbGVgKSBvciBjaGVja2JveCAoYG11bHRpYCkuICovXG4gIGdyb3VwU2VsZWN0aW9uPzogJ3NpbmdsZScgfCAnbXVsdGknO1xuICAvKiogRWxpZ2libGUgZm9yIGlkZW50aWZ5IC8gR2V0RmVhdHVyZUluZm8uICovXG4gIHF1ZXJ5YWJsZT86IGJvb2xlYW47XG4gIGxlZ2VuZFVybD86IHN0cmluZztcbiAgcHJvamVjdGlvbj86IHN0cmluZztcbiAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZW9NYXBPc21MYXllckNvbmZpZyBleHRlbmRzIEdlb01hcExheWVyQmFzZSB7XG4gIHR5cGU6ICdvc20nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEdlb01hcFh5ekxheWVyQ29uZmlnIGV4dGVuZHMgR2VvTWFwTGF5ZXJCYXNlIHtcbiAgdHlwZTogJ3h5eic7XG4gIHVybDogc3RyaW5nO1xuICBhdHRyaWJ1dGlvbnM/OiBzdHJpbmcgfCBzdHJpbmdbXTtcbiAgbWF4Wm9vbT86IG51bWJlcjtcbiAgY3Jvc3NPcmlnaW4/OiBzdHJpbmcgfCBudWxsO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEdlb01hcFdtc0xheWVyQ29uZmlnIGV4dGVuZHMgR2VvTWFwTGF5ZXJCYXNlIHtcbiAgdHlwZTogJ3dtcyc7XG4gIHVybDogc3RyaW5nO1xuICBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4+O1xuICBzZXJ2ZXJUeXBlPzogJ2dlb3NlcnZlcicgfCAnbWFwc2VydmVyJyB8ICdxZ2lzJyB8ICdjYXJtZW50YXNlcnZlcic7XG4gIGNyb3NzT3JpZ2luPzogc3RyaW5nIHwgbnVsbDtcbiAgLyoqIE9wdGlvbmFsIFdNUyBsYXllciBuYW1lIHdoZW4gbm90IG9ubHkgaW4gYHBhcmFtcy5MQVlFUlNgLiAqL1xuICBsYXllck5hbWU/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2VvTWFwV210c0xheWVyQ29uZmlnIGV4dGVuZHMgR2VvTWFwTGF5ZXJCYXNlIHtcbiAgdHlwZTogJ3dtdHMnO1xuICB1cmw6IHN0cmluZztcbiAgbGF5ZXI6IHN0cmluZztcbiAgbWF0cml4U2V0OiBzdHJpbmc7XG4gIGZvcm1hdD86IHN0cmluZztcbiAgc3R5bGU/OiBzdHJpbmc7XG4gIHByb2plY3Rpb24/OiBzdHJpbmc7XG4gIGNyb3NzT3JpZ2luPzogc3RyaW5nIHwgbnVsbDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZW9NYXBHZW9Kc29uTGF5ZXJDb25maWcgZXh0ZW5kcyBHZW9NYXBMYXllckJhc2Uge1xuICB0eXBlOiAnZ2VvanNvbic7XG4gIC8qKiBJbmxpbmUgR2VvSlNPTiBvYmplY3Qgb3IgVVJMIHN0cmluZy4gKi9cbiAgZGF0YTogb2JqZWN0IHwgc3RyaW5nO1xuICBkYXRhUHJvamVjdGlvbj86IHN0cmluZztcbiAgZmVhdHVyZVByb2plY3Rpb24/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2VvTWFwVmVjdG9yTGF5ZXJDb25maWcgZXh0ZW5kcyBHZW9NYXBMYXllckJhc2Uge1xuICB0eXBlOiAndmVjdG9yJztcbiAgLyoqIFByZS1idWlsdCBPTCBmZWF0dXJlcyAoYXBwLW93bmVkKS4gKi9cbiAgZmVhdHVyZXM/OiBGZWF0dXJlPEdlb21ldHJ5PltdO1xufVxuXG5leHBvcnQgdHlwZSBHZW9NYXBMYXllckNvbmZpZyA9XG4gIHwgR2VvTWFwT3NtTGF5ZXJDb25maWdcbiAgfCBHZW9NYXBYeXpMYXllckNvbmZpZ1xuICB8IEdlb01hcFdtc0xheWVyQ29uZmlnXG4gIHwgR2VvTWFwV210c0xheWVyQ29uZmlnXG4gIHwgR2VvTWFwR2VvSnNvbkxheWVyQ29uZmlnXG4gIHwgR2VvTWFwVmVjdG9yTGF5ZXJDb25maWc7XG5cbmV4cG9ydCB0eXBlIEdlb01hcEJhc2VtYXBJbnB1dCA9XG4gIHwgJ29zbSdcbiAgfCB7XG4gICAgICB0eXBlOiAneHl6JztcbiAgICAgIHVybDogc3RyaW5nO1xuICAgICAgYXR0cmlidXRpb25zPzogc3RyaW5nIHwgc3RyaW5nW107XG4gICAgICBtYXhab29tPzogbnVtYmVyO1xuICAgICAgdGl0bGU/OiBzdHJpbmc7XG4gICAgfTtcblxuLyoqIEFsaWFzIHVzZWQgYnkgYmFzZW1hcCBzd2l0Y2hlciBvdXRwdXQuICovXG5leHBvcnQgdHlwZSBHZW9NYXBCYXNlbWFwID0gR2VvTWFwQmFzZW1hcElucHV0O1xuXG5leHBvcnQgaW50ZXJmYWNlIEdlb01hcEJhc2VtYXBPcHRpb24ge1xuICBpZDogc3RyaW5nO1xuICBsYWJlbDogc3RyaW5nO1xuICBiYXNlbWFwOiBHZW9NYXBCYXNlbWFwO1xuICBwcmV2aWV3VXJsPzogc3RyaW5nO1xufVxuXG5leHBvcnQgdHlwZSBHZW9NYXBMb2NhdGVFcnJvclJlYXNvbiA9XG4gIHwgJ3Vuc3VwcG9ydGVkJ1xuICB8ICdkZW5pZWQnXG4gIHwgJ3VuYXZhaWxhYmxlJ1xuICB8ICd0aW1lb3V0J1xuICB8ICd1bmtub3duJztcblxuZXhwb3J0IGludGVyZmFjZSBHZW9NYXBDbGlja0V2ZW50IHtcbiAgLyoqIENvb3JkaW5hdGUgaW4gdmlldyBwcm9qZWN0aW9uLiAqL1xuICBjb29yZGluYXRlOiBudW1iZXJbXTtcbiAgLyoqIExvbi9sYXQgKEVQU0c6NDMyNikgYXMgW2xvbmdpdHVkZSwgbGF0aXR1ZGVdLiAqL1xuICBsb25MYXQ6IFtudW1iZXIsIG51bWJlcl07XG4gIHBpeGVsOiBbbnVtYmVyLCBudW1iZXJdO1xuICBvcmlnaW5hbEV2ZW50OiBVSUV2ZW50O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEdlb01hcFZpZXdDaGFuZ2VFdmVudCB7XG4gIGNlbnRlcjogbnVtYmVyW107XG4gIHpvb206IG51bWJlcjtcbiAgcmVzb2x1dGlvbjogbnVtYmVyO1xuICByb3RhdGlvbjogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEdlb01hcExheWVyVmlzaWJpbGl0eUNoYW5nZSB7XG4gIGxheWVySWQ6IHN0cmluZztcbiAgdmlzaWJsZTogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZW9NYXBMYXllck9wYWNpdHlDaGFuZ2Uge1xuICBsYXllcklkOiBzdHJpbmc7XG4gIG9wYWNpdHk6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZW9NYXBMYXllclJ1bnRpbWVTdGF0ZSB7XG4gIGlkOiBzdHJpbmc7XG4gIHN0YXR1czogR2VvTWFwTGF5ZXJTdGF0dXM7XG4gIGVycm9yTWVzc2FnZT86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZW9NYXBDb29yZGluYXRlIHtcbiAgLyoqIFt4LCB5XSBvciBbbG9uZ2l0dWRlLCBsYXRpdHVkZV0gaW4gYHByb2plY3Rpb25gLiAqL1xuICBjb29yZGluYXRlczogW251bWJlciwgbnVtYmVyXTtcbiAgcHJvamVjdGlvbjogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE1hcEluaXRPcHRpb25zIHtcbiAgdGFyZ2V0OiBIVE1MRWxlbWVudDtcbiAgY2VudGVyOiBudW1iZXJbXTtcbiAgem9vbTogbnVtYmVyO1xuICBtaW5ab29tOiBudW1iZXI7XG4gIG1heFpvb206IG51bWJlcjtcbiAgdmlld1Byb2plY3Rpb246IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZW9NYXBMZWdlbmRJdGVtIHtcbiAgbGFiZWw6IHN0cmluZztcbiAgLyoqIE9wdGlvbmFsIGxhbmQtdXNlIGNvZGUgKGUuZy4gT05ULCBTS0MpLiAqL1xuICBjb2RlPzogc3RyaW5nO1xuICAvKiogQ1NTIGNvbG9yIGZvciBzd2F0Y2gg4oCUIHByZWZlciBkZXNpZ24gdG9rZW5zIHdoZW4gcG9zc2libGUuICovXG4gIGNvbG9yPzogc3RyaW5nO1xuICBzd2F0Y2hVcmw/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCB0eXBlIEdlb01hcE1lYXN1cmVNb2RlID0gJ25vbmUnIHwgJ2Rpc3RhbmNlJyB8ICdhcmVhJztcblxuZXhwb3J0IGludGVyZmFjZSBHZW9NYXBNZWFzdXJlUmVzdWx0IHtcbiAgbW9kZTogRXhjbHVkZTxHZW9NYXBNZWFzdXJlTW9kZSwgJ25vbmUnPjtcbiAgLyoqIFJhdyB2YWx1ZSBpbiBtZXRlcnMgKGRpc3RhbmNlKSBvciBtwrIgKGFyZWEpLiAqL1xuICB2YWx1ZTogbnVtYmVyO1xuICAvKiogSHVtYW4tcmVhZGFibGUgbGFiZWwgKG0va20gb3IgbcKyL2hhKS4gKi9cbiAgbGFiZWw6IHN0cmluZztcbiAgZ2VvbWV0cnk6IEdlb21ldHJ5IHwgbnVsbDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZW9NYXBUb29sYmFyQWN0aW9uIHtcbiAgaWQ6IHN0cmluZztcbiAgbGFiZWw/OiBzdHJpbmc7XG4gIC8qKiBuZy16b3JybyAvIGdlby1pY29uIHR5cGUgKGZhbGxiYWNrIHdoZW4gYGljb25TcmNgIGlzIG9taXR0ZWQpLiAqL1xuICBpY29uPzogc3RyaW5nO1xuICAvKiogRXhwb3J0ZWQgRmlnbWEgLyBzdGF0aWMgYXNzZXQgVVJMIChwcmVmZXIgb3ZlciBgaWNvbmApLiAqL1xuICBpY29uU3JjPzogc3RyaW5nO1xuICBhY3RpdmU/OiBib29sZWFuO1xuICBjaGVja2VkPzogYm9vbGVhbjtcbiAgZGlzYWJsZWQ/OiBib29sZWFuO1xuICBpY29uT25seT86IGJvb2xlYW47XG4gIHRvb2x0aXA/OiBzdHJpbmc7XG4gIC8qKiBGaWxsZWQgcHJpbWFyeSBjb250cm9sIChlLmcuIEhvbWUpLiAqL1xuICB2YXJpYW50PzogJ2RlZmF1bHQnIHwgJ3ByaW1hcnknO1xufVxuXG4vKiogU2VhcmNoIG1vZGVzIGZvciBwb3J0YWwgdHJhIGPhu6l1IChUQ1FILjfigJMxMSkuICovXG5leHBvcnQgdHlwZSBHZW9NYXBTZWFyY2hNb2RlID1cbiAgfCAnb3duZXInXG4gIHwgJ2NlcnRpZmljYXRlJ1xuICB8ICdjb29yZGluYXRlcydcbiAgfCAnYWRkcmVzcydcbiAgfCAncGFyY2VsJztcblxuZXhwb3J0IGludGVyZmFjZSBHZW9NYXBTZWFyY2hRdWVyeSB7XG4gIG1vZGU6IEdlb01hcFNlYXJjaE1vZGU7XG4gIC8qKiBGaWVsZCB2YWx1ZXMga2V5ZWQgYnkgbW9kZS1zcGVjaWZpYyBpbnB1dCBpZHMuICovXG4gIHZhbHVlczogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZW9NYXBTZWFyY2hSZXN1bHRJdGVtIHtcbiAgaWQ6IHN0cmluZztcbiAgdGl0bGU6IHN0cmluZztcbiAgc3VidGl0bGU/OiBzdHJpbmc7XG4gIC8qKiBMb24vbGF0IGNlbnRlciBmb3IgcGFuIChFUFNHOjQzMjYpLiAqL1xuICBjZW50ZXI0MzI2PzogW251bWJlciwgbnVtYmVyXTtcbiAgLyoqIExvbi9sYXQgZXh0ZW50IGZvciBmaXQgKEVQU0c6NDMyNikuICovXG4gIGV4dGVudDQzMjY/OiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbiAgLyoqIE9wdGlvbmFsIEdlb0pTT04gRmVhdHVyZSAvIEZlYXR1cmVDb2xsZWN0aW9uIGZvciBtYXAgaGlnaGxpZ2h0LiAqL1xuICBnZW9qc29uPzogb2JqZWN0O1xuICAvKiogRGV0YWlsIHBheWxvYWQgZm9yIGBnZW8tbWFwLXBhcmNlbC1wb3B1cGAuICovXG4gIHBhcmNlbD86IEdlb01hcFBhcmNlbERldGFpbDtcbn1cblxuLyoqIEF1ZGllbmNlIGNvbnRyb2xzIHdoaWNoIHBhcmNlbCBmaWVsZHMgYXJlIHNob3duIChUQ1FILjEyKS4gKi9cbmV4cG9ydCB0eXBlIEdlb01hcFBhcmNlbEF1ZGllbmNlID0gJ2NpdGl6ZW4nIHwgJ3NwZWNpYWxpc3QnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEdlb01hcFBhcmNlbERldGFpbCB7XG4gIC8qKiBNw6MgdGjhu61hIMSR4bqldCAoaGnhu4NuIHRo4buLIOG7nyBUaMO0bmcgdGluIGNodW5nKS4gKi9cbiAgcGFyY2VsQ29kZT86IHN0cmluZztcbiAgcGFyY2VsTnVtYmVyPzogc3RyaW5nO1xuICBzaGVldE51bWJlcj86IHN0cmluZztcbiAgd2FyZD86IHN0cmluZztcbiAgcHJvdmluY2U/OiBzdHJpbmc7XG4gIGFyZWE/OiBzdHJpbmc7XG4gIGxlZ2FsQXJlYT86IHN0cmluZztcbiAgbGFuZFVzZT86IHN0cmluZztcbiAgYWRkcmVzcz86IHN0cmluZztcbiAgdXNlRm9ybT86IHN0cmluZztcbiAgcmVnaXN0cmF0aW9uU3RhdHVzPzogc3RyaW5nO1xuICAvKiogQ2h1ecOqbiB2acOqbiAvIG3hu58gcuG7mW5nLiAqL1xuICBzaGFwZUluZm8/OiBzdHJpbmc7XG4gIHBsYW5uaW5nSW5mbz86IHN0cmluZztcbiAgLyoqIEdpw6EgxJHhuqV0IOKAlCBt4bq3YyDEkeG7i25oIFVJIGhp4buHbiDCq8SQYW5nIGPhuq1wIG5o4bqtdMK7IG7hur91IHRy4buRbmcuICovXG4gIGxhbmRQcmljZT86IHN0cmluZztcbiAgLyoqIFVSTCDhuqNuaCBzxqEgxJHhu5MgdGjhu61hICh0deG7syBjaOG7jW4pLiAqL1xuICBkaWFncmFtVXJsPzogc3RyaW5nO1xuICAvKiogRXh0cmEgcm93cyB3aGVuIGhvc3QgbmVlZHMgbW9yZSBmaWVsZHMuICovXG4gIGV4dHJhRmllbGRzPzogQXJyYXk8eyBsYWJlbDogc3RyaW5nOyB2YWx1ZTogc3RyaW5nIH0+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEdlb01hcEhpZ2hsaWdodE9wdGlvbnMge1xuICBkYXRhUHJvamVjdGlvbj86IHN0cmluZztcbiAgLyoqIEZpdCB2aWV3IHRvIGhpZ2hsaWdodCBleHRlbnQgKGRlZmF1bHQgdHJ1ZSB3aGVuIGZlYXR1cmVzIGV4aXN0KS4gKi9cbiAgZml0PzogYm9vbGVhbjtcbiAgZml0T3B0aW9ucz86IHsgcGFkZGluZz86IG51bWJlcltdOyBtYXhab29tPzogbnVtYmVyOyBkdXJhdGlvbj86IG51bWJlciB9O1xufVxuIl19
@@ -0,0 +1,368 @@
1
+ import { Injectable, inject } from '@angular/core';
2
+ import GeoJSON from 'ol/format/GeoJSON';
3
+ import TileLayer from 'ol/layer/Tile';
4
+ import VectorLayer from 'ol/layer/Vector';
5
+ import OSM from 'ol/source/OSM';
6
+ import TileWMS from 'ol/source/TileWMS';
7
+ import VectorSource from 'ol/source/Vector';
8
+ import XYZ from 'ol/source/XYZ';
9
+ import WMTS from 'ol/source/WMTS';
10
+ import WMTSTileGrid from 'ol/tilegrid/WMTS';
11
+ import { get as getProjection } from 'ol/proj';
12
+ import { getTopLeft, getWidth } from 'ol/extent';
13
+ import { GEO_MAP_BASEMAP_LAYER_ID } from '../geo-map.constants';
14
+ import { GeoMapProjectionService } from './geo-map-projection.service';
15
+ import * as i0 from "@angular/core";
16
+ const LAYER_ID_KEY = 'geoLayerId';
17
+ const LAYER_BASEMAP_KEY = 'geoBasemap';
18
+ const LAYER_GROUP_KEY = 'geoGroup';
19
+ const LAYER_QUERYABLE_KEY = 'geoQueryable';
20
+ /**
21
+ * Builds and incrementally patches OpenLayers layers from typed configs.
22
+ * Visibility / opacity updates must not recreate sources.
23
+ */
24
+ export class GeoMapLayerService {
25
+ projection = inject(GeoMapProjectionService);
26
+ runtime = new Map();
27
+ getRuntimeState(layerId) {
28
+ return this.runtime.get(layerId);
29
+ }
30
+ getAllRuntimeStates() {
31
+ return [...this.runtime.values()];
32
+ }
33
+ createFromBasemapInput(basemap) {
34
+ if (basemap === 'osm') {
35
+ const config = {
36
+ id: GEO_MAP_BASEMAP_LAYER_ID,
37
+ title: 'OpenStreetMap',
38
+ type: 'osm',
39
+ visible: true,
40
+ opacity: 1,
41
+ zIndex: 0,
42
+ basemap: true,
43
+ group: 'base-map',
44
+ };
45
+ return this.createLayer(config);
46
+ }
47
+ const config = {
48
+ id: GEO_MAP_BASEMAP_LAYER_ID,
49
+ title: basemap.title ?? 'XYZ basemap',
50
+ type: 'xyz',
51
+ url: basemap.url,
52
+ attributions: basemap.attributions,
53
+ maxZoom: basemap.maxZoom,
54
+ visible: true,
55
+ opacity: 1,
56
+ zIndex: 0,
57
+ basemap: true,
58
+ group: 'base-map',
59
+ };
60
+ return this.createLayer(config);
61
+ }
62
+ createLayer(config) {
63
+ this.runtime.set(config.id, { id: config.id, status: 'loading' });
64
+ let layer;
65
+ try {
66
+ this.validateConfig(config);
67
+ switch (config.type) {
68
+ case 'osm':
69
+ layer = this.createOsmLayer(config);
70
+ break;
71
+ case 'xyz':
72
+ layer = this.createXyzLayer(config);
73
+ break;
74
+ case 'wms':
75
+ layer = this.createWmsLayer(config);
76
+ break;
77
+ case 'wmts':
78
+ layer = this.createWmtsLayer(config);
79
+ break;
80
+ case 'geojson':
81
+ layer = this.createGeoJsonLayer(config);
82
+ break;
83
+ case 'vector':
84
+ layer = this.createVectorLayer(config);
85
+ break;
86
+ default: {
87
+ const _exhaustive = config;
88
+ throw new Error(`Unsupported layer type: ${JSON.stringify(_exhaustive)}`);
89
+ }
90
+ }
91
+ this.applyCommonOptions(layer, config);
92
+ this.wireSourceStatus(config.id, layer);
93
+ this.runtime.set(config.id, { id: config.id, status: 'ready' });
94
+ }
95
+ catch (err) {
96
+ const message = err instanceof Error ? err.message : String(err);
97
+ console.error(`[GeoMapLayerService] Failed to create layer "${config.id}"`, err);
98
+ this.runtime.set(config.id, {
99
+ id: config.id,
100
+ status: 'error',
101
+ errorMessage: message,
102
+ });
103
+ // Placeholder invisible layer so callers can still track id
104
+ layer = new VectorLayer({
105
+ source: new VectorSource(),
106
+ visible: false,
107
+ });
108
+ this.applyCommonOptions(layer, { ...config, visible: false });
109
+ }
110
+ return { id: config.id, config, layer };
111
+ }
112
+ /**
113
+ * Apply visibility/opacity/zIndex without recreating the OL layer.
114
+ * Returns true when structural fields changed and the layer should be recreated.
115
+ */
116
+ needsRecreate(previous, next) {
117
+ if (previous.type !== next.type || previous.id !== next.id) {
118
+ return true;
119
+ }
120
+ switch (next.type) {
121
+ case 'osm':
122
+ return false;
123
+ case 'xyz':
124
+ return (previous.url !== next.url ||
125
+ previous.maxZoom !== next.maxZoom);
126
+ case 'wms':
127
+ return (previous.url !== next.url ||
128
+ JSON.stringify(previous.params) !==
129
+ JSON.stringify(next.params) ||
130
+ previous.layerName !== next.layerName);
131
+ case 'wmts':
132
+ return (previous.url !== next.url ||
133
+ previous.layer !== next.layer ||
134
+ previous.matrixSet !== next.matrixSet);
135
+ case 'geojson':
136
+ return (JSON.stringify(previous.data) !==
137
+ JSON.stringify(next.data) ||
138
+ previous.dataProjection !== next.dataProjection);
139
+ case 'vector':
140
+ return previous.features !== next.features;
141
+ default:
142
+ return true;
143
+ }
144
+ }
145
+ patchLayer(layer, config) {
146
+ layer.setVisible(config.visible ?? true);
147
+ layer.setOpacity(config.opacity ?? 1);
148
+ if (config.zIndex != null) {
149
+ layer.setZIndex(config.zIndex);
150
+ }
151
+ if (config.minZoom != null) {
152
+ layer.setMinZoom(config.minZoom);
153
+ }
154
+ if (config.maxZoom != null) {
155
+ layer.setMaxZoom(config.maxZoom);
156
+ }
157
+ layer.set(LAYER_BASEMAP_KEY, !!config.basemap);
158
+ layer.set(LAYER_GROUP_KEY, config.group ?? '');
159
+ layer.set(LAYER_QUERYABLE_KEY, !!config.queryable);
160
+ }
161
+ setVisible(layer, visible) {
162
+ layer.setVisible(visible);
163
+ }
164
+ setOpacity(layer, opacity) {
165
+ const clamped = Math.min(1, Math.max(0, opacity));
166
+ layer.setOpacity(clamped);
167
+ }
168
+ getLayerId(layer) {
169
+ const id = layer.get(LAYER_ID_KEY);
170
+ return typeof id === 'string' ? id : undefined;
171
+ }
172
+ isBasemap(layer) {
173
+ return !!layer.get(LAYER_BASEMAP_KEY);
174
+ }
175
+ resolveBasemapExclusive(layers, activeBasemapId) {
176
+ for (const item of layers) {
177
+ if (!item.config.basemap) {
178
+ continue;
179
+ }
180
+ const visible = item.id === activeBasemapId;
181
+ item.layer.setVisible(visible);
182
+ item.config = { ...item.config, visible };
183
+ }
184
+ }
185
+ validateConfig(config) {
186
+ if (!config.id?.trim()) {
187
+ throw new Error('Layer config requires a non-empty id.');
188
+ }
189
+ if (config.type === 'xyz' && !config.url?.trim()) {
190
+ throw new Error(`XYZ layer "${config.id}" is missing url.`);
191
+ }
192
+ if (config.type === 'wms') {
193
+ if (!config.url?.trim()) {
194
+ throw new Error(`WMS layer "${config.id}" is missing url.`);
195
+ }
196
+ const layersParam = config.layerName ??
197
+ (config.params['LAYERS'] != null ? String(config.params['LAYERS']) : '');
198
+ if (!layersParam) {
199
+ throw new Error(`WMS layer "${config.id}" needs layerName or params.LAYERS.`);
200
+ }
201
+ }
202
+ if (config.type === 'wmts') {
203
+ if (!config.url?.trim() || !config.layer?.trim() || !config.matrixSet?.trim()) {
204
+ throw new Error(`WMTS layer "${config.id}" requires url, layer, and matrixSet.`);
205
+ }
206
+ }
207
+ if (config.type === 'geojson' && config.data == null) {
208
+ throw new Error(`GeoJSON layer "${config.id}" is missing data.`);
209
+ }
210
+ }
211
+ applyCommonOptions(layer, config) {
212
+ layer.set(LAYER_ID_KEY, config.id);
213
+ layer.set(LAYER_BASEMAP_KEY, !!config.basemap);
214
+ layer.set(LAYER_GROUP_KEY, config.group ?? '');
215
+ layer.set(LAYER_QUERYABLE_KEY, !!config.queryable);
216
+ layer.setVisible(config.visible ?? true);
217
+ layer.setOpacity(config.opacity ?? 1);
218
+ if (config.zIndex != null) {
219
+ layer.setZIndex(config.zIndex);
220
+ }
221
+ if (config.minZoom != null) {
222
+ layer.setMinZoom(config.minZoom);
223
+ }
224
+ if (config.maxZoom != null) {
225
+ layer.setMaxZoom(config.maxZoom);
226
+ }
227
+ }
228
+ wireSourceStatus(layerId, layer) {
229
+ if (!(layer instanceof TileLayer)) {
230
+ return;
231
+ }
232
+ const source = layer.getSource();
233
+ if (!source) {
234
+ return;
235
+ }
236
+ source.on('tileloaderror', () => {
237
+ console.warn(`[GeoMapLayerService] Tile error on layer "${layerId}"`);
238
+ this.runtime.set(layerId, {
239
+ id: layerId,
240
+ status: 'error',
241
+ errorMessage: 'Không tải được dữ liệu lớp bản đồ.',
242
+ });
243
+ });
244
+ source.on('tileloadend', () => {
245
+ const current = this.runtime.get(layerId);
246
+ if (current?.status === 'error') {
247
+ return;
248
+ }
249
+ this.runtime.set(layerId, { id: layerId, status: 'ready' });
250
+ });
251
+ }
252
+ createOsmLayer(_config) {
253
+ return new TileLayer({
254
+ source: new OSM(),
255
+ });
256
+ }
257
+ createXyzLayer(config) {
258
+ return new TileLayer({
259
+ source: new XYZ({
260
+ url: config.url,
261
+ attributions: config.attributions,
262
+ maxZoom: config.maxZoom,
263
+ crossOrigin: config.crossOrigin ?? 'anonymous',
264
+ }),
265
+ });
266
+ }
267
+ createWmsLayer(config) {
268
+ const layers = config.layerName ??
269
+ (config.params['LAYERS'] != null ? String(config.params['LAYERS']) : '');
270
+ const params = {
271
+ ...config.params,
272
+ LAYERS: layers,
273
+ };
274
+ return new TileLayer({
275
+ source: new TileWMS({
276
+ url: config.url,
277
+ params,
278
+ serverType: config.serverType,
279
+ crossOrigin: config.crossOrigin ?? 'anonymous',
280
+ projection: config.projection,
281
+ }),
282
+ });
283
+ }
284
+ createWmtsLayer(config) {
285
+ const projectionCode = config.projection ?? 'EPSG:3857';
286
+ this.projection.ensureRegistered(projectionCode);
287
+ const projection = getProjection(projectionCode);
288
+ if (!projection) {
289
+ throw new Error(`WMTS projection "${projectionCode}" is not available.`);
290
+ }
291
+ const projectionExtent = projection.getExtent();
292
+ if (!projectionExtent) {
293
+ throw new Error(`WMTS projection "${projectionCode}" has no extent; provide a custom tile grid in a later phase.`);
294
+ }
295
+ const size = getWidth(projectionExtent) / 256;
296
+ const resolutions = [];
297
+ const matrixIds = [];
298
+ for (let z = 0; z < 20; z += 1) {
299
+ resolutions[z] = size / Math.pow(2, z);
300
+ matrixIds[z] = String(z);
301
+ }
302
+ return new TileLayer({
303
+ source: new WMTS({
304
+ url: config.url,
305
+ layer: config.layer,
306
+ matrixSet: config.matrixSet,
307
+ format: config.format ?? 'image/png',
308
+ style: config.style ?? '',
309
+ projection: projectionCode,
310
+ crossOrigin: config.crossOrigin ?? 'anonymous',
311
+ tileGrid: new WMTSTileGrid({
312
+ origin: getTopLeft(projectionExtent),
313
+ resolutions,
314
+ matrixIds,
315
+ }),
316
+ }),
317
+ });
318
+ }
319
+ createGeoJsonLayer(config) {
320
+ const format = new GeoJSON();
321
+ const source = new VectorSource();
322
+ const featureProjection = config.featureProjection ?? 'EPSG:3857';
323
+ const dataProjection = config.dataProjection ?? 'EPSG:4326';
324
+ if (typeof config.data === 'string') {
325
+ // URL — let VectorSource load asynchronously
326
+ const urlSource = new VectorSource({
327
+ url: config.data,
328
+ format: new GeoJSON({
329
+ dataProjection,
330
+ featureProjection,
331
+ }),
332
+ });
333
+ urlSource.on('featuresloaderror', () => {
334
+ console.error(`[GeoMapLayerService] GeoJSON load error "${config.id}"`);
335
+ this.runtime.set(config.id, {
336
+ id: config.id,
337
+ status: 'error',
338
+ errorMessage: 'Không tải được GeoJSON.',
339
+ });
340
+ });
341
+ return new VectorLayer({ source: urlSource });
342
+ }
343
+ try {
344
+ const features = format.readFeatures(config.data, {
345
+ dataProjection,
346
+ featureProjection,
347
+ });
348
+ source.addFeatures(features);
349
+ }
350
+ catch (err) {
351
+ console.error(`[GeoMapLayerService] Invalid GeoJSON for "${config.id}"`, err);
352
+ throw new Error(`GeoJSON không hợp lệ cho lớp "${config.id}".`);
353
+ }
354
+ return new VectorLayer({ source });
355
+ }
356
+ createVectorLayer(config) {
357
+ const source = new VectorSource({
358
+ features: config.features ?? [],
359
+ });
360
+ return new VectorLayer({ source });
361
+ }
362
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GeoMapLayerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
363
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GeoMapLayerService });
364
+ }
365
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GeoMapLayerService, decorators: [{
366
+ type: Injectable
367
+ }] });
368
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VvLW1hcC1sYXllci5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZ2VvLXVpL3NyYy9saWIvZmlnbWEvZ2VvLW1hcC9zZXJ2aWNlcy9nZW8tbWFwLWxheWVyLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFbkQsT0FBTyxPQUFPLE1BQU0sbUJBQW1CLENBQUM7QUFHeEMsT0FBTyxTQUFTLE1BQU0sZUFBZSxDQUFDO0FBQ3RDLE9BQU8sV0FBVyxNQUFNLGlCQUFpQixDQUFDO0FBQzFDLE9BQU8sR0FBRyxNQUFNLGVBQWUsQ0FBQztBQUNoQyxPQUFPLE9BQU8sTUFBTSxtQkFBbUIsQ0FBQztBQUN4QyxPQUFPLFlBQVksTUFBTSxrQkFBa0IsQ0FBQztBQUM1QyxPQUFPLEdBQUcsTUFBTSxlQUFlLENBQUM7QUFFaEMsT0FBTyxJQUFJLE1BQU0sZ0JBQWdCLENBQUM7QUFDbEMsT0FBTyxZQUFZLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxFQUFFLEdBQUcsSUFBSSxhQUFhLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDL0MsT0FBTyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDakQsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFZaEUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sOEJBQThCLENBQUM7O0FBRXZFLE1BQU0sWUFBWSxHQUFHLFlBQVksQ0FBQztBQUNsQyxNQUFNLGlCQUFpQixHQUFHLFlBQVksQ0FBQztBQUN2QyxNQUFNLGVBQWUsR0FBRyxVQUFVLENBQUM7QUFDbkMsTUFBTSxtQkFBbUIsR0FBRyxjQUFjLENBQUM7QUFRM0M7OztHQUdHO0FBRUgsTUFBTSxPQUFPLGtCQUFrQjtJQUNaLFVBQVUs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QztZQUNILE9BQU8sSUFBSSxXQUFXLENBQUMsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztRQUNoRCxDQUFDO1FBRUQsSUFBSSxDQUFDO1lBQ0gsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFO2dCQUNoRCxjQUFjO2dCQUNkLGlCQUFpQjthQUNsQixDQUF3QixDQUFDO1lBQzFCLE1BQU0sQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDL0IsQ0FBQztRQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7WUFDYixPQUFPLENBQUMsS0FBSyxDQUFDLDZDQUE2QyxNQUFNLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDOUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxpQ0FBaUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDbEUsQ0FBQztRQUVELE9BQU8sSUFBSSxXQUFXLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFTyxpQkFBaUIsQ0FBQyxNQUErQjtRQUN2RCxNQUFNLE1BQU0sR0FBRyxJQUFJLFlBQVksQ0FBQztZQUM5QixRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVEsSUFBSSxFQUFFO1NBQ2hDLENBQUMsQ0FBQztRQUNILE9BQU8sSUFBSSxXQUFXLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQ3JDLENBQUM7d0dBL1hVLGtCQUFrQjs0R0FBbEIsa0JBQWtCOzs0RkFBbEIsa0JBQWtCO2tCQUQ5QixVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgRmVhdHVyZSBmcm9tICdvbC9GZWF0dXJlJztcbmltcG9ydCBHZW9KU09OIGZyb20gJ29sL2Zvcm1hdC9HZW9KU09OJztcbmltcG9ydCB0eXBlIEdlb21ldHJ5IGZyb20gJ29sL2dlb20vR2VvbWV0cnknO1xuaW1wb3J0IHR5cGUgQmFzZUxheWVyIGZyb20gJ29sL2xheWVyL0Jhc2UnO1xuaW1wb3J0IFRpbGVMYXllciBmcm9tICdvbC9sYXllci9UaWxlJztcbmltcG9ydCBWZWN0b3JMYXllciBmcm9tICdvbC9sYXllci9WZWN0b3InO1xuaW1wb3J0IE9TTSBmcm9tICdvbC9zb3VyY2UvT1NNJztcbmltcG9ydCBUaWxlV01TIGZyb20gJ29sL3NvdXJjZS9UaWxlV01TJztcbmltcG9ydCBWZWN0b3JTb3VyY2UgZnJvbSAnb2wvc291cmNlL1ZlY3Rvcic7XG5pbXBvcnQgWFlaIGZyb20gJ29sL3NvdXJjZS9YWVonO1xuaW1wb3J0IHR5cGUgeyBQcm9qZWN0aW9uTGlrZSB9IGZyb20gJ29sL3Byb2onO1xuaW1wb3J0IFdNVFMgZnJvbSAnb2wvc291cmNlL1dNVFMnO1xuaW1wb3J0IFdNVFNUaWxlR3JpZCBmcm9tICdvbC90aWxlZ3JpZC9XTVRTJztcbmltcG9ydCB7IGdldCBhcyBnZXRQcm9qZWN0aW9uIH0gZnJvbSAnb2wvcHJvaic7XG5pbXBvcnQgeyBnZXRUb3BMZWZ0LCBnZXRXaWR0aCB9IGZyb20gJ29sL2V4dGVudCc7XG5pbXBvcnQgeyBHRU9fTUFQX0JBU0VNQVBfTEFZRVJfSUQgfSBmcm9tICcuLi9nZW8tbWFwLmNvbnN0YW50cyc7XG5pbXBvcnQgdHlwZSB7XG4gIEdlb01hcEJhc2VtYXBJbnB1dCxcbiAgR2VvTWFwR2VvSnNvbkxheWVyQ29uZmlnLFxuICBHZW9NYXBMYXllckNvbmZpZyxcbiAgR2VvTWFwTGF5ZXJSdW50aW1lU3RhdGUsXG4gIEdlb01hcE9zbUxheWVyQ29uZmlnLFxuICBHZW9NYXBWZWN0b3JMYXllckNvbmZpZyxcbiAgR2VvTWFwV21zTGF5ZXJDb25maWcsXG4gIEdlb01hcFdtdHNMYXllckNvbmZpZyxcbiAgR2VvTWFwWHl6TGF5ZXJDb25maWcsXG59IGZyb20gJy4uL2dlby1tYXAudHlwZXMnO1xuaW1wb3J0IHsgR2VvTWFwUHJvamVjdGlvblNlcnZpY2UgfSBmcm9tICcuL2dlby1tYXAtcHJvamVjdGlvbi5zZXJ2aWNlJztcblxuY29uc3QgTEFZRVJfSURfS0VZID0gJ2dlb0xheWVySWQnO1xuY29uc3QgTEFZRVJfQkFTRU1BUF9LRVkgPSAnZ2VvQmFzZW1hcCc7XG5jb25zdCBMQVlFUl9HUk9VUF9LRVkgPSAnZ2VvR3JvdXAnO1xuY29uc3QgTEFZRVJfUVVFUllBQkxFX0tFWSA9ICdnZW9RdWVyeWFibGUnO1xuXG5leHBvcnQgaW50ZXJmYWNlIENyZWF0ZWRNYXBMYXllciB7XG4gIGlkOiBzdHJpbmc7XG4gIGNvbmZpZzogR2VvTWFwTGF5ZXJDb25maWc7XG4gIGxheWVyOiBCYXNlTGF5ZXI7XG59XG5cbi8qKlxuICogQnVpbGRzIGFuZCBpbmNyZW1lbnRhbGx5IHBhdGNoZXMgT3BlbkxheWVycyBsYXllcnMgZnJvbSB0eXBlZCBjb25maWdzLlxuICogVmlzaWJpbGl0eSAvIG9wYWNpdHkgdXBkYXRlcyBtdXN0IG5vdCByZWNyZWF0ZSBzb3VyY2VzLlxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgR2VvTWFwTGF5ZXJTZXJ2aWNlIHtcbiAgcHJpdmF0ZSByZWFkb25seSBwcm9qZWN0aW9uID0gaW5qZWN0KEdlb01hcFByb2plY3Rpb25TZXJ2aWNlKTtcbiAgcHJpdmF0ZSByZWFkb25seSBydW50aW1lID0gbmV3IE1hcDxzdHJpbmcsIEdlb01hcExheWVyUnVudGltZVN0YXRlPigpO1xuXG4gIGdldFJ1bnRpbWVTdGF0ZShsYXllcklkOiBzdHJpbmcpOiBHZW9NYXBMYXllclJ1bnRpbWVTdGF0ZSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMucnVudGltZS5nZXQobGF5ZXJJZCk7XG4gIH1cblxuICBnZXRBbGxSdW50aW1lU3RhdGVzKCk6IEdlb01hcExheWVyUnVudGltZVN0YXRlW10ge1xuICAgIHJldHVybiBbLi4udGhpcy5ydW50aW1lLnZhbHVlcygpXTtcbiAgfVxuXG4gIGNyZWF0ZUZyb21CYXNlbWFwSW5wdXQoYmFzZW1hcDogR2VvTWFwQmFzZW1hcElucHV0KTogQ3JlYXRlZE1hcExheWVyIHtcbiAgICBpZiAoYmFzZW1hcCA9PT0gJ29zbScpIHtcbiAgICAgIGNvbnN0IGNvbmZpZzogR2VvTWFwT3NtTGF5ZXJDb25maWcgPSB7XG4gICAgICAgIGlkOiBHRU9fTUFQX0JBU0VNQVBfTEFZRVJfSUQsXG4gICAgICAgIHRpdGxlOiAnT3BlblN0cmVldE1hcCcsXG4gICAgICAgIHR5cGU6ICdvc20nLFxuICAgICAgICB2aXNpYmxlOiB0cnVlLFxuICAgICAgICBvcGFjaXR5OiAxLFxuICAgICAgICB6SW5kZXg6IDAsXG4gICAgICAgIGJhc2VtYXA6IHRydWUsXG4gICAgICAgIGdyb3VwOiAnYmFzZS1tYXAnLFxuICAgICAgfTtcbiAgICAgIHJldHVybiB0aGlzLmNyZWF0ZUxheWVyKGNvbmZpZyk7XG4gICAgfVxuXG4gICAgY29uc3QgY29uZmlnOiBHZW9NYXBYeXpMYXllckNvbmZpZyA9IHtcbiAgICAgIGlkOiBHRU9fTUFQX0JBU0VNQVBfTEFZRVJfSUQsXG4gICAgICB0aXRsZTogYmFzZW1hcC50aXRsZSA/PyAnWFlaIGJhc2VtYXAnLFxuICAgICAgdHlwZTogJ3h5eicsXG4gICAgICB1cmw6IGJhc2VtYXAudXJsLFxuICAgICAgYXR0cmlidXRpb25zOiBiYXNlbWFwLmF0dHJpYnV0aW9ucyxcbiAgICAgIG1heFpvb206IGJhc2VtYXAubWF4Wm9vbSxcbiAgICAgIHZpc2libGU6IHRydWUsXG4gICAgICBvcGFjaXR5OiAxLFxuICAgICAgekluZGV4OiAwLFxuICAgICAgYmFzZW1hcDogdHJ1ZSxcbiAgICAgIGdyb3VwOiAnYmFzZS1tYXAnLFxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlTGF5ZXIoY29uZmlnKTtcbiAgfVxuXG4gIGNyZWF0ZUxheWVyKGNvbmZpZzogR2VvTWFwTGF5ZXJDb25maWcpOiBDcmVhdGVkTWFwTGF5ZXIge1xuICAgIHRoaXMucnVudGltZS5zZXQoY29uZmlnLmlkLCB7IGlkOiBjb25maWcuaWQsIHN0YXR1czogJ2xvYWRpbmcnIH0pO1xuXG4gICAgbGV0IGxheWVyOiBCYXNlTGF5ZXI7XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMudmFsaWRhdGVDb25maWcoY29uZmlnKTtcbiAgICAgIHN3aXRjaCAoY29uZmlnLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnb3NtJzpcbiAgICAgICAgICBsYXllciA9IHRoaXMuY3JlYXRlT3NtTGF5ZXIoY29uZmlnKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAneHl6JzpcbiAgICAgICAgICBsYXllciA9IHRoaXMuY3JlYXRlWHl6TGF5ZXIoY29uZmlnKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnd21zJzpcbiAgICAgICAgICBsYXllciA9IHRoaXMuY3JlYXRlV21zTGF5ZXIoY29uZmlnKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnd210cyc6XG4gICAgICAgICAgbGF5ZXIgPSB0aGlzLmNyZWF0ZVdtdHNMYXllcihjb25maWcpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdnZW9qc29uJzpcbiAgICAgICAgICBsYXllciA9IHRoaXMuY3JlYXRlR2VvSnNvbkxheWVyKGNvbmZpZyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3ZlY3Rvcic6XG4gICAgICAgICAgbGF5ZXIgPSB0aGlzLmNyZWF0ZVZlY3RvckxheWVyKGNvbmZpZyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgICBjb25zdCBfZXhoYXVzdGl2ZTogbmV2ZXIgPSBjb25maWc7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBsYXllciB0eXBlOiAke0pTT04uc3RyaW5naWZ5KF9leGhhdXN0aXZlKX1gKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhpcy5hcHBseUNvbW1vbk9wdGlvbnMobGF5ZXIsIGNvbmZpZyk7XG4gICAgICB0aGlzLndpcmVTb3VyY2VTdGF0dXMoY29uZmlnLmlkLCBsYXllcik7XG4gICAgICB0aGlzLnJ1bnRpbWUuc2V0KGNvbmZpZy5pZCwgeyBpZDogY29uZmlnLmlkLCBzdGF0dXM6ICdyZWFkeScgfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zdCBtZXNzYWdlID0gZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpO1xuICAgICAgY29uc29sZS5lcnJvcihgW0dlb01hcExheWVyU2VydmljZV0gRmFpbGVkIHRvIGNyZWF0ZSBsYXllciBcIiR7Y29uZmlnLmlkfVwiYCwgZXJyKTtcbiAgICAgIHRoaXMucnVudGltZS5zZXQoY29uZmlnLmlkLCB7XG4gICAgICAgIGlkOiBjb25maWcuaWQsXG4gICAgICAgIHN0YXR1czogJ2Vycm9yJyxcbiAgICAgICAgZXJyb3JNZXNzYWdlOiBtZXNzYWdlLFxuICAgICAgfSk7XG4gICAgICAvLyBQbGFjZWhvbGRlciBpbnZpc2libGUgbGF5ZXIgc28gY2FsbGVycyBjYW4gc3RpbGwgdHJhY2sgaWRcbiAgICAgIGxheWVyID0gbmV3IFZlY3RvckxheWVyKHtcbiAgICAgICAgc291cmNlOiBuZXcgVmVjdG9yU291cmNlKCksXG4gICAgICAgIHZpc2libGU6IGZhbHNlLFxuICAgICAgfSk7XG4gICAgICB0aGlzLmFwcGx5Q29tbW9uT3B0aW9ucyhsYXllciwgeyAuLi5jb25maWcsIHZpc2libGU6IGZhbHNlIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB7IGlkOiBjb25maWcuaWQsIGNvbmZpZywgbGF5ZXIgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBseSB2aXNpYmlsaXR5L29wYWNpdHkvekluZGV4IHdpdGhvdXQgcmVjcmVhdGluZyB0aGUgT0wgbGF5ZXIuXG4gICAqIFJldHVybnMgdHJ1ZSB3aGVuIHN0cnVjdHVyYWwgZmllbGRzIGNoYW5nZWQgYW5kIHRoZSBsYXllciBzaG91bGQgYmUgcmVjcmVhdGVkLlxuICAgKi9cbiAgbmVlZHNSZWNyZWF0ZShwcmV2aW91czogR2VvTWFwTGF5ZXJDb25maWcsIG5leHQ6IEdlb01hcExheWVyQ29uZmlnKTogYm9vbGVhbiB7XG4gICAgaWYgKHByZXZpb3VzLnR5cGUgIT09IG5leHQudHlwZSB8fCBwcmV2aW91cy5pZCAhPT0gbmV4dC5pZCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHN3aXRjaCAobmV4dC50eXBlKSB7XG4gICAgICBjYXNlICdvc20nOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBjYXNlICd4eXonOlxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIChwcmV2aW91cyBhcyBHZW9NYXBYeXpMYXllckNvbmZpZykudXJsICE9PSBuZXh0LnVybCB8fFxuICAgICAgICAgIChwcmV2aW91cyBhcyBHZW9NYXBYeXpMYXllckNvbmZpZykubWF4Wm9vbSAhPT0gbmV4dC5tYXhab29tXG4gICAgICAgICk7XG4gICAgICBjYXNlICd3bXMnOlxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIChwcmV2aW91cyBhcyBHZW9NYXBXbXNMYXllckNvbmZpZykudXJsICE9PSBuZXh0LnVybCB8fFxuICAgICAgICAgIEpTT04uc3RyaW5naWZ5KChwcmV2aW91cyBhcyBHZW9NYXBXbXNMYXllckNvbmZpZykucGFyYW1zKSAhPT1cbiAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KG5leHQucGFyYW1zKSB8fFxuICAgICAgICAgIChwcmV2aW91cyBhcyBHZW9NYXBXbXNMYXllckNvbmZpZykubGF5ZXJOYW1lICE9PSBuZXh0LmxheWVyTmFtZVxuICAgICAgICApO1xuICAgICAgY2FzZSAnd210cyc6XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgKHByZXZpb3VzIGFzIEdlb01hcFdtdHNMYXllckNvbmZpZykudXJsICE9PSBuZXh0LnVybCB8fFxuICAgICAgICAgIChwcmV2aW91cyBhcyBHZW9NYXBXbXRzTGF5ZXJDb25maWcpLmxheWVyICE9PSBuZXh0LmxheWVyIHx8XG4gICAgICAgICAgKHByZXZpb3VzIGFzIEdlb01hcFdtdHNMYXllckNvbmZpZykubWF0cml4U2V0ICE9PSBuZXh0Lm1hdHJpeFNldFxuICAgICAgICApO1xuICAgICAgY2FzZSAnZ2VvanNvbic6XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgSlNPTi5zdHJpbmdpZnkoKHByZXZpb3VzIGFzIEdlb01hcEdlb0pzb25MYXllckNvbmZpZykuZGF0YSkgIT09XG4gICAgICAgICAgICBKU09OLnN0cmluZ2lmeShuZXh0LmRhdGEpIHx8XG4gICAgICAgICAgKHByZXZpb3VzIGFzIEdlb01hcEdlb0pzb25MYXllckNvbmZpZykuZGF0YVByb2plY3Rpb24gIT09IG5leHQuZGF0YVByb2plY3Rpb25cbiAgICAgICAgKTtcbiAgICAgIGNhc2UgJ3ZlY3Rvcic6XG4gICAgICAgIHJldHVybiAocHJldmlvdXMgYXMgR2VvTWFwVmVjdG9yTGF5ZXJDb25maWcpLmZlYXR1cmVzICE9PSBuZXh0LmZlYXR1cmVzO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcGF0Y2hMYXllcihsYXllcjogQmFzZUxheWVyLCBjb25maWc6IEdlb01hcExheWVyQ29uZmlnKTogdm9pZCB7XG4gICAgbGF5ZXIuc2V0VmlzaWJsZShjb25maWcudmlzaWJsZSA/PyB0cnVlKTtcbiAgICBsYXllci5zZXRPcGFjaXR5KGNvbmZpZy5vcGFjaXR5ID8/IDEpO1xuICAgIGlmIChjb25maWcuekluZGV4ICE9IG51bGwpIHtcbiAgICAgIGxheWVyLnNldFpJbmRleChjb25maWcuekluZGV4KTtcbiAgICB9XG4gICAgaWYgKGNvbmZpZy5taW5ab29tICE9IG51bGwpIHtcbiAgICAgIGxheWVyLnNldE1pblpvb20oY29uZmlnLm1pblpvb20pO1xuICAgIH1cbiAgICBpZiAoY29uZmlnLm1heFpvb20gIT0gbnVsbCkge1xuICAgICAgbGF5ZXIuc2V0TWF4Wm9vbShjb25maWcubWF4Wm9vbSk7XG4gICAgfVxuICAgIGxheWVyLnNldChMQVlFUl9CQVNFTUFQX0tFWSwgISFjb25maWcuYmFzZW1hcCk7XG4gICAgbGF5ZXIuc2V0KExBWUVSX0dST1VQX0tFWSwgY29uZmlnLmdyb3VwID8/ICcnKTtcbiAgICBsYXllci5zZXQoTEFZRVJfUVVFUllBQkxFX0tFWSwgISFjb25maWcucXVlcnlhYmxlKTtcbiAgfVxuXG4gIHNldFZpc2libGUobGF5ZXI6IEJhc2VMYXllciwgdmlzaWJsZTogYm9vbGVhbik6IHZvaWQge1xuICAgIGxheWVyLnNldFZpc2libGUodmlzaWJsZSk7XG4gIH1cblxuICBzZXRPcGFjaXR5KGxheWVyOiBCYXNlTGF5ZXIsIG9wYWNpdHk6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IGNsYW1wZWQgPSBNYXRoLm1pbigxLCBNYXRoLm1heCgwLCBvcGFjaXR5KSk7XG4gICAgbGF5ZXIuc2V0T3BhY2l0eShjbGFtcGVkKTtcbiAgfVxuXG4gIGdldExheWVySWQobGF5ZXI6IEJhc2VMYXllcik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgaWQgPSBsYXllci5nZXQoTEFZRVJfSURfS0VZKTtcbiAgICByZXR1cm4gdHlwZW9mIGlkID09PSAnc3RyaW5nJyA/IGlkIDogdW5kZWZpbmVkO1xuICB9XG5cbiAgaXNCYXNlbWFwKGxheWVyOiBCYXNlTGF5ZXIpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISFsYXllci5nZXQoTEFZRVJfQkFTRU1BUF9LRVkpO1xuICB9XG5cbiAgcmVzb2x2ZUJhc2VtYXBFeGNsdXNpdmUoXG4gICAgbGF5ZXJzOiBDcmVhdGVkTWFwTGF5ZXJbXSxcbiAgICBhY3RpdmVCYXNlbWFwSWQ6IHN0cmluZyxcbiAgKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBpdGVtIG9mIGxheWVycykge1xuICAgICAgaWYgKCFpdGVtLmNvbmZpZy5iYXNlbWFwKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgdmlzaWJsZSA9IGl0ZW0uaWQgPT09IGFjdGl2ZUJhc2VtYXBJZDtcbiAgICAgIGl0ZW0ubGF5ZXIuc2V0VmlzaWJsZSh2aXNpYmxlKTtcbiAgICAgIGl0ZW0uY29uZmlnID0geyAuLi5pdGVtLmNvbmZpZywgdmlzaWJsZSB9O1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVDb25maWcoY29uZmlnOiBHZW9NYXBMYXllckNvbmZpZyk6IHZvaWQge1xuICAgIGlmICghY29uZmlnLmlkPy50cmltKCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTGF5ZXIgY29uZmlnIHJlcXVpcmVzIGEgbm9uLWVtcHR5IGlkLicpO1xuICAgIH1cbiAgICBpZiAoY29uZmlnLnR5cGUgPT09ICd4eXonICYmICFjb25maWcudXJsPy50cmltKCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgWFlaIGxheWVyIFwiJHtjb25maWcuaWR9XCIgaXMgbWlzc2luZyB1cmwuYCk7XG4gICAgfVxuICAgIGlmIChjb25maWcudHlwZSA9PT0gJ3dtcycpIHtcbiAgICAgIGlmICghY29uZmlnLnVybD8udHJpbSgpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgV01TIGxheWVyIFwiJHtjb25maWcuaWR9XCIgaXMgbWlzc2luZyB1cmwuYCk7XG4gICAgICB9XG4gICAgICBjb25zdCBsYXllcnNQYXJhbSA9XG4gICAgICAgIGNvbmZpZy5sYXllck5hbWUgPz9cbiAgICAgICAgKGNvbmZpZy5wYXJhbXNbJ0xBWUVSUyddICE9IG51bGwgPyBTdHJpbmcoY29uZmlnLnBhcmFtc1snTEFZRVJTJ10pIDogJycpO1xuICAgICAgaWYgKCFsYXllcnNQYXJhbSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYFdNUyBsYXllciBcIiR7Y29uZmlnLmlkfVwiIG5lZWRzIGxheWVyTmFtZSBvciBwYXJhbXMuTEFZRVJTLmAsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChjb25maWcudHlwZSA9PT0gJ3dtdHMnKSB7XG4gICAgICBpZiAoIWNvbmZpZy51cmw/LnRyaW0oKSB8fCAhY29uZmlnLmxheWVyPy50cmltKCkgfHwgIWNvbmZpZy5tYXRyaXhTZXQ/LnRyaW0oKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYFdNVFMgbGF5ZXIgXCIke2NvbmZpZy5pZH1cIiByZXF1aXJlcyB1cmwsIGxheWVyLCBhbmQgbWF0cml4U2V0LmAsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChjb25maWcudHlwZSA9PT0gJ2dlb2pzb24nICYmIGNvbmZpZy5kYXRhID09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgR2VvSlNPTiBsYXllciBcIiR7Y29uZmlnLmlkfVwiIGlzIG1pc3NpbmcgZGF0YS5gKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFwcGx5Q29tbW9uT3B0aW9ucyhsYXllcjogQmFzZUxheWVyLCBjb25maWc6IEdlb01hcExheWVyQ29uZmlnKTogdm9pZCB7XG4gICAgbGF5ZXIuc2V0KExBWUVSX0lEX0tFWSwgY29uZmlnLmlkKTtcbiAgICBsYXllci5zZXQoTEFZRVJfQkFTRU1BUF9LRVksICEhY29uZmlnLmJhc2VtYXApO1xuICAgIGxheWVyLnNldChMQVlFUl9HUk9VUF9LRVksIGNvbmZpZy5ncm91cCA/PyAnJyk7XG4gICAgbGF5ZXIuc2V0KExBWUVSX1FVRVJZQUJMRV9LRVksICEhY29uZmlnLnF1ZXJ5YWJsZSk7XG4gICAgbGF5ZXIuc2V0VmlzaWJsZShjb25maWcudmlzaWJsZSA/PyB0cnVlKTtcbiAgICBsYXllci5zZXRPcGFjaXR5KGNvbmZpZy5vcGFjaXR5ID8/IDEpO1xuICAgIGlmIChjb25maWcuekluZGV4ICE9IG51bGwpIHtcbiAgICAgIGxheWVyLnNldFpJbmRleChjb25maWcuekluZGV4KTtcbiAgICB9XG4gICAgaWYgKGNvbmZpZy5taW5ab29tICE9IG51bGwpIHtcbiAgICAgIGxheWVyLnNldE1pblpvb20oY29uZmlnLm1pblpvb20pO1xuICAgIH1cbiAgICBpZiAoY29uZmlnLm1heFpvb20gIT0gbnVsbCkge1xuICAgICAgbGF5ZXIuc2V0TWF4Wm9vbShjb25maWcubWF4Wm9vbSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB3aXJlU291cmNlU3RhdHVzKGxheWVySWQ6IHN0cmluZywgbGF5ZXI6IEJhc2VMYXllcik6IHZvaWQge1xuICAgIGlmICghKGxheWVyIGluc3RhbmNlb2YgVGlsZUxheWVyKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBzb3VyY2UgPSBsYXllci5nZXRTb3VyY2UoKTtcbiAgICBpZiAoIXNvdXJjZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHNvdXJjZS5vbigndGlsZWxvYWRlcnJvcicsICgpID0+IHtcbiAgICAgIGNvbnNvbGUud2FybihgW0dlb01hcExheWVyU2VydmljZV0gVGlsZSBlcnJvciBvbiBsYXllciBcIiR7bGF5ZXJJZH1cImApO1xuICAgICAgdGhpcy5ydW50aW1lLnNldChsYXllcklkLCB7XG4gICAgICAgIGlkOiBsYXllcklkLFxuICAgICAgICBzdGF0dXM6ICdlcnJvcicsXG4gICAgICAgIGVycm9yTWVzc2FnZTogJ0tow7RuZyB04bqjaSDEkcaw4bujYyBk4buvIGxp4buHdSBs4bubcCBi4bqjbiDEkeG7ky4nLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBzb3VyY2Uub24oJ3RpbGVsb2FkZW5kJywgKCkgPT4ge1xuICAgICAgY29uc3QgY3VycmVudCA9IHRoaXMucnVudGltZS5nZXQobGF5ZXJJZCk7XG4gICAgICBpZiAoY3VycmVudD8uc3RhdHVzID09PSAnZXJyb3InKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRoaXMucnVudGltZS5zZXQobGF5ZXJJZCwgeyBpZDogbGF5ZXJJZCwgc3RhdHVzOiAncmVhZHknIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVPc21MYXllcihfY29uZmlnOiBHZW9NYXBPc21MYXllckNvbmZpZyk6IFRpbGVMYXllcjxPU00+IHtcbiAgICByZXR1cm4gbmV3IFRpbGVMYXllcih7XG4gICAgICBzb3VyY2U6IG5ldyBPU00oKSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlWHl6TGF5ZXIoY29uZmlnOiBHZW9NYXBYeXpMYXllckNvbmZpZyk6IFRpbGVMYXllcjxYWVo+IHtcbiAgICByZXR1cm4gbmV3IFRpbGVMYXllcih7XG4gICAgICBzb3VyY2U6IG5ldyBYWVooe1xuICAgICAgICB1cmw6IGNvbmZpZy51cmwsXG4gICAgICAgIGF0dHJpYnV0aW9uczogY29uZmlnLmF0dHJpYnV0aW9ucyxcbiAgICAgICAgbWF4Wm9vbTogY29uZmlnLm1heFpvb20sXG4gICAgICAgIGNyb3NzT3JpZ2luOiBjb25maWcuY3Jvc3NPcmlnaW4gPz8gJ2Fub255bW91cycsXG4gICAgICB9KSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlV21zTGF5ZXIoY29uZmlnOiBHZW9NYXBXbXNMYXllckNvbmZpZyk6IFRpbGVMYXllcjxUaWxlV01TPiB7XG4gICAgY29uc3QgbGF5ZXJzID1cbiAgICAgIGNvbmZpZy5sYXllck5hbWUgPz9cbiAgICAgIChjb25maWcucGFyYW1zWydMQVlFUlMnXSAhPSBudWxsID8gU3RyaW5nKGNvbmZpZy5wYXJhbXNbJ0xBWUVSUyddKSA6ICcnKTtcbiAgICBjb25zdCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4+ID0ge1xuICAgICAgLi4uY29uZmlnLnBhcmFtcyxcbiAgICAgIExBWUVSUzogbGF5ZXJzLFxuICAgIH07XG4gICAgcmV0dXJuIG5ldyBUaWxlTGF5ZXIoe1xuICAgICAgc291cmNlOiBuZXcgVGlsZVdNUyh7XG4gICAgICAgIHVybDogY29uZmlnLnVybCxcbiAgICAgICAgcGFyYW1zLFxuICAgICAgICBzZXJ2ZXJUeXBlOiBjb25maWcuc2VydmVyVHlwZSxcbiAgICAgICAgY3Jvc3NPcmlnaW46IGNvbmZpZy5jcm9zc09yaWdpbiA/PyAnYW5vbnltb3VzJyxcbiAgICAgICAgcHJvamVjdGlvbjogY29uZmlnLnByb2plY3Rpb24gYXMgUHJvamVjdGlvbkxpa2UgfCB1bmRlZmluZWQsXG4gICAgICB9KSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlV210c0xheWVyKGNvbmZpZzogR2VvTWFwV210c0xheWVyQ29uZmlnKTogVGlsZUxheWVyPFdNVFM+IHtcbiAgICBjb25zdCBwcm9qZWN0aW9uQ29kZSA9IGNvbmZpZy5wcm9qZWN0aW9uID8/ICdFUFNHOjM4NTcnO1xuICAgIHRoaXMucHJvamVjdGlvbi5lbnN1cmVSZWdpc3RlcmVkKHByb2plY3Rpb25Db2RlKTtcbiAgICBjb25zdCBwcm9qZWN0aW9uID0gZ2V0UHJvamVjdGlvbihwcm9qZWN0aW9uQ29kZSk7XG4gICAgaWYgKCFwcm9qZWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFdNVFMgcHJvamVjdGlvbiBcIiR7cHJvamVjdGlvbkNvZGV9XCIgaXMgbm90IGF2YWlsYWJsZS5gKTtcbiAgICB9XG4gICAgY29uc3QgcHJvamVjdGlvbkV4dGVudCA9IHByb2plY3Rpb24uZ2V0RXh0ZW50KCk7XG4gICAgaWYgKCFwcm9qZWN0aW9uRXh0ZW50KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBXTVRTIHByb2plY3Rpb24gXCIke3Byb2plY3Rpb25Db2RlfVwiIGhhcyBubyBleHRlbnQ7IHByb3ZpZGUgYSBjdXN0b20gdGlsZSBncmlkIGluIGEgbGF0ZXIgcGhhc2UuYCxcbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnN0IHNpemUgPSBnZXRXaWR0aChwcm9qZWN0aW9uRXh0ZW50KSAvIDI1NjtcbiAgICBjb25zdCByZXNvbHV0aW9uczogbnVtYmVyW10gPSBbXTtcbiAgICBjb25zdCBtYXRyaXhJZHM6IHN0cmluZ1tdID0gW107XG4gICAgZm9yIChsZXQgeiA9IDA7IHogPCAyMDsgeiArPSAxKSB7XG4gICAgICByZXNvbHV0aW9uc1t6XSA9IHNpemUgLyBNYXRoLnBvdygyLCB6KTtcbiAgICAgIG1hdHJpeElkc1t6XSA9IFN0cmluZyh6KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFRpbGVMYXllcih7XG4gICAgICBzb3VyY2U6IG5ldyBXTVRTKHtcbiAgICAgICAgdXJsOiBjb25maWcudXJsLFxuICAgICAgICBsYXllcjogY29uZmlnLmxheWVyLFxuICAgICAgICBtYXRyaXhTZXQ6IGNvbmZpZy5tYXRyaXhTZXQsXG4gICAgICAgIGZvcm1hdDogY29uZmlnLmZvcm1hdCA/PyAnaW1hZ2UvcG5nJyxcbiAgICAgICAgc3R5bGU6IGNvbmZpZy5zdHlsZSA/PyAnJyxcbiAgICAgICAgcHJvamVjdGlvbjogcHJvamVjdGlvbkNvZGUsXG4gICAgICAgIGNyb3NzT3JpZ2luOiBjb25maWcuY3Jvc3NPcmlnaW4gPz8gJ2Fub255bW91cycsXG4gICAgICAgIHRpbGVHcmlkOiBuZXcgV01UU1RpbGVHcmlkKHtcbiAgICAgICAgICBvcmlnaW46IGdldFRvcExlZnQocHJvamVjdGlvbkV4dGVudCksXG4gICAgICAgICAgcmVzb2x1dGlvbnMsXG4gICAgICAgICAgbWF0cml4SWRzLFxuICAgICAgICB9KSxcbiAgICAgIH0pLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVHZW9Kc29uTGF5ZXIoY29uZmlnOiBHZW9NYXBHZW9Kc29uTGF5ZXJDb25maWcpOiBWZWN0b3JMYXllcjxWZWN0b3JTb3VyY2U+IHtcbiAgICBjb25zdCBmb3JtYXQgPSBuZXcgR2VvSlNPTigpO1xuICAgIGNvbnN0IHNvdXJjZSA9IG5ldyBWZWN0b3JTb3VyY2UoKTtcbiAgICBjb25zdCBmZWF0dXJlUHJvamVjdGlvbiA9IGNvbmZpZy5mZWF0dXJlUHJvamVjdGlvbiA/PyAnRVBTRzozODU3JztcbiAgICBjb25zdCBkYXRhUHJvamVjdGlvbiA9IGNvbmZpZy5kYXRhUHJvamVjdGlvbiA/PyAnRVBTRzo0MzI2JztcblxuICAgIGlmICh0eXBlb2YgY29uZmlnLmRhdGEgPT09ICdzdHJpbmcnKSB7XG4gICAgICAvLyBVUkwg4oCUIGxldCBWZWN0b3JTb3VyY2UgbG9hZCBhc3luY2hyb25vdXNseVxuICAgICAgY29uc3QgdXJsU291cmNlID0gbmV3IFZlY3RvclNvdXJjZSh7XG4gICAgICAgIHVybDogY29uZmlnLmRhdGEsXG4gICAgICAgIGZvcm1hdDogbmV3IEdlb0pTT04oe1xuICAgICAgICAgIGRhdGFQcm9qZWN0aW9uLFxuICAgICAgICAgIGZlYXR1cmVQcm9qZWN0aW9uLFxuICAgICAgICB9KSxcbiAgICAgIH0pO1xuICAgICAgdXJsU291cmNlLm9uKCdmZWF0dXJlc2xvYWRlcnJvcicsICgpID0+IHtcbiAgICAgICAgY29uc29sZS5lcnJvcihgW0dlb01hcExheWVyU2VydmljZV0gR2VvSlNPTiBsb2FkIGVycm9yIFwiJHtjb25maWcuaWR9XCJgKTtcbiAgICAgICAgdGhpcy5ydW50aW1lLnNldChjb25maWcuaWQsIHtcbiAgICAgICAgICBpZDogY29uZmlnLmlkLFxuICAgICAgICAgIHN0YXR1czogJ2Vycm9yJyxcbiAgICAgICAgICBlcnJvck1lc3NhZ2U6ICdLaMO0bmcgdOG6o2kgxJHGsOG7o2MgR2VvSlNPTi4nLFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG5ldyBWZWN0b3JMYXllcih7IHNvdXJjZTogdXJsU291cmNlIH0pO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBmZWF0dXJlcyA9IGZvcm1hdC5yZWFkRmVhdHVyZXMoY29uZmlnLmRhdGEsIHtcbiAgICAgICAgZGF0YVByb2plY3Rpb24sXG4gICAgICAgIGZlYXR1cmVQcm9qZWN0aW9uLFxuICAgICAgfSkgYXMgRmVhdHVyZTxHZW9tZXRyeT5bXTtcbiAgICAgIHNvdXJjZS5hZGRGZWF0dXJlcyhmZWF0dXJlcyk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGBbR2VvTWFwTGF5ZXJTZXJ2aWNlXSBJbnZhbGlkIEdlb0pTT04gZm9yIFwiJHtjb25maWcuaWR9XCJgLCBlcnIpO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBHZW9KU09OIGtow7RuZyBo4bujcCBs4buHIGNobyBs4bubcCBcIiR7Y29uZmlnLmlkfVwiLmApO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgVmVjdG9yTGF5ZXIoeyBzb3VyY2UgfSk7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVZlY3RvckxheWVyKGNvbmZpZzogR2VvTWFwVmVjdG9yTGF5ZXJDb25maWcpOiBWZWN0b3JMYXllcjxWZWN0b3JTb3VyY2U+IHtcbiAgICBjb25zdCBzb3VyY2UgPSBuZXcgVmVjdG9yU291cmNlKHtcbiAgICAgIGZlYXR1cmVzOiBjb25maWcuZmVhdHVyZXMgPz8gW10sXG4gICAgfSk7XG4gICAgcmV0dXJuIG5ldyBWZWN0b3JMYXllcih7IHNvdXJjZSB9KTtcbiAgfVxufVxuIl19
@@ -0,0 +1,110 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { get as getProjection, transform, transformExtent } from 'ol/proj';
3
+ import { register } from 'ol/proj/proj4';
4
+ import proj4 from 'proj4';
5
+ import { GEO_MAP_BUILTIN_PROJECTIONS } from '../geo-map.constants';
6
+ import * as i0 from "@angular/core";
7
+ export class GeoMapProjectionError extends Error {
8
+ constructor(message) {
9
+ super(message);
10
+ this.name = 'GeoMapProjectionError';
11
+ }
12
+ }
13
+ /**
14
+ * Central proj4 / OpenLayers projection registration and transforms.
15
+ * Keep all CRS logic here — components must not call proj4 directly.
16
+ */
17
+ export class GeoMapProjectionService {
18
+ registeredCodes = new Set(GEO_MAP_BUILTIN_PROJECTIONS);
19
+ isRegistered(code) {
20
+ const normalized = this.normalizeCode(code);
21
+ if (this.registeredCodes.has(normalized)) {
22
+ return true;
23
+ }
24
+ return getProjection(normalized) != null;
25
+ }
26
+ /**
27
+ * Register a custom CRS (e.g. local VN-2000). Definition must come from config/API.
28
+ */
29
+ registerProjection(config) {
30
+ const code = this.normalizeCode(config.code);
31
+ if (!config.definition?.trim()) {
32
+ throw new GeoMapProjectionError(`Projection "${code}" is missing a proj4 definition. Supply it from environment or API.`);
33
+ }
34
+ try {
35
+ proj4.defs(code, config.definition.trim());
36
+ register(proj4);
37
+ }
38
+ catch (err) {
39
+ const detail = err instanceof Error ? err.message : String(err);
40
+ throw new GeoMapProjectionError(`Invalid proj4 definition for "${code}": ${detail}`);
41
+ }
42
+ const projection = getProjection(code);
43
+ if (!projection) {
44
+ throw new GeoMapProjectionError(`OpenLayers did not create projection "${code}" after registration.`);
45
+ }
46
+ if (config.extent) {
47
+ projection.setExtent(config.extent);
48
+ }
49
+ this.registeredCodes.add(code);
50
+ }
51
+ ensureRegistered(code) {
52
+ const normalized = this.normalizeCode(code);
53
+ if (!this.isRegistered(normalized)) {
54
+ throw new GeoMapProjectionError(`Projection "${normalized}" is not registered. Call registerProjection() with a valid definition first.`);
55
+ }
56
+ }
57
+ /**
58
+ * Transform a coordinate. Order is always [x, y] / [longitude, latitude].
59
+ */
60
+ transformCoordinate(coordinate, fromProjection, toProjection) {
61
+ if (coordinate.length < 2) {
62
+ throw new GeoMapProjectionError('Coordinate must have at least two values [x, y].');
63
+ }
64
+ const from = this.normalizeCode(fromProjection);
65
+ const to = this.normalizeCode(toProjection);
66
+ this.ensureRegistered(from);
67
+ this.ensureRegistered(to);
68
+ if (from === to) {
69
+ return [Number(coordinate[0]), Number(coordinate[1])];
70
+ }
71
+ const result = transform([Number(coordinate[0]), Number(coordinate[1])], from, to);
72
+ return [result[0], result[1]];
73
+ }
74
+ transformExtent(extent, fromProjection, toProjection) {
75
+ const from = this.normalizeCode(fromProjection);
76
+ const to = this.normalizeCode(toProjection);
77
+ this.ensureRegistered(from);
78
+ this.ensureRegistered(to);
79
+ if (from === to) {
80
+ return [...extent];
81
+ }
82
+ const result = transformExtent(extent, from, to);
83
+ return [result[0], result[1], result[2], result[3]];
84
+ }
85
+ /**
86
+ * Normalize user input: trim, upper-case EPSG codes, reject non-finite numbers.
87
+ */
88
+ normalizeCoordinate(value, options) {
89
+ const label = options?.label ?? 'coordinate';
90
+ if (!Array.isArray(value) || value.length < 2) {
91
+ throw new GeoMapProjectionError(`Invalid ${label}: expected [x, y] or [longitude, latitude].`);
92
+ }
93
+ const x = Number(value[0]);
94
+ const y = Number(value[1]);
95
+ if (!Number.isFinite(x) || !Number.isFinite(y)) {
96
+ throw new GeoMapProjectionError(`Invalid ${label}: values must be finite numbers.`);
97
+ }
98
+ return [x, y];
99
+ }
100
+ normalizeCode(code) {
101
+ return code.trim();
102
+ }
103
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GeoMapProjectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
104
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GeoMapProjectionService, providedIn: 'root' });
105
+ }
106
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GeoMapProjectionService, decorators: [{
107
+ type: Injectable,
108
+ args: [{ providedIn: 'root' }]
109
+ }] });
110
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VvLW1hcC1wcm9qZWN0aW9uLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9nZW8tdWkvc3JjL2xpYi9maWdtYS9nZW8tbWFwL3NlcnZpY2VzL2dlby1tYXAtcHJvamVjdGlvbi5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLEdBQUcsSUFBSSxhQUFhLEVBQUUsU0FBUyxFQUFFLGVBQWUsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUMzRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUMxQixPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQzs7QUFHbkUsTUFBTSxPQUFPLHFCQUFzQixTQUFRLEtBQUs7SUFDOUMsWUFBWSxPQUFlO1FBQ3pCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsdUJBQXVCLENBQUM7SUFDdEMsQ0FBQztDQUNGO0FBRUQ7OztHQUdHO0FBRUgsTUFBTSxPQUFPLHVCQUF1QjtJQUNqQixlQUFlLEdBQUcsSUFBSSxHQUFHLENBQVMsMkJBQTJCLENBQUMsQ0FBQztJQUVoRixZQUFZLENBQUMsSUFBWTtRQUN2QixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzVDLElBQUksSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztZQUN6QyxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFDRCxPQUFPLGFBQWEsQ0FBQyxVQUFVLENBQUMsSUFBSSxJQUFJLENBQUM7SUFDM0MsQ0FBQztJQUVEOztPQUVHO0lBQ0gsa0JBQWtCLENBQUMs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LFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUMvQyxNQUFNLElBQUkscUJBQXFCLENBQUMsV0FBVyxLQUFLLGtDQUFrQyxDQUFDLENBQUM7UUFDdEYsQ0FBQztRQUNELE9BQU8sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEIsQ0FBQztJQUVELGFBQWEsQ0FBQyxJQUFZO1FBQ3hCLE9BQU8sSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ3JCLENBQUM7d0dBNUhVLHVCQUF1Qjs0R0FBdkIsdUJBQXVCLGNBRFYsTUFBTTs7NEZBQ25CLHVCQUF1QjtrQkFEbkMsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBnZXQgYXMgZ2V0UHJvamVjdGlvbiwgdHJhbnNmb3JtLCB0cmFuc2Zvcm1FeHRlbnQgfSBmcm9tICdvbC9wcm9qJztcbmltcG9ydCB7IHJlZ2lzdGVyIH0gZnJvbSAnb2wvcHJvai9wcm9qNCc7XG5pbXBvcnQgcHJvajQgZnJvbSAncHJvajQnO1xuaW1wb3J0IHsgR0VPX01BUF9CVUlMVElOX1BST0pFQ1RJT05TIH0gZnJvbSAnLi4vZ2VvLW1hcC5jb25zdGFudHMnO1xuaW1wb3J0IHR5cGUgeyBQcm9qZWN0aW9uQ29uZmlnIH0gZnJvbSAnLi4vZ2VvLW1hcC50eXBlcyc7XG5cbmV4cG9ydCBjbGFzcyBHZW9NYXBQcm9qZWN0aW9uRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZykge1xuICAgIHN1cGVyKG1lc3NhZ2UpO1xuICAgIHRoaXMubmFtZSA9ICdHZW9NYXBQcm9qZWN0aW9uRXJyb3InO1xuICB9XG59XG5cbi8qKlxuICogQ2VudHJhbCBwcm9qNCAvIE9wZW5MYXllcnMgcHJvamVjdGlvbiByZWdpc3RyYXRpb24gYW5kIHRyYW5zZm9ybXMuXG4gKiBLZWVwIGFsbCBDUlMgbG9naWMgaGVyZSDigJQgY29tcG9uZW50cyBtdXN0IG5vdCBjYWxsIHByb2o0IGRpcmVjdGx5LlxuICovXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIEdlb01hcFByb2plY3Rpb25TZXJ2aWNlIHtcbiAgcHJpdmF0ZSByZWFkb25seSByZWdpc3RlcmVkQ29kZXMgPSBuZXcgU2V0PHN0cmluZz4oR0VPX01BUF9CVUlMVElOX1BST0pFQ1RJT05TKTtcblxuICBpc1JlZ2lzdGVyZWQoY29kZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgbm9ybWFsaXplZCA9IHRoaXMubm9ybWFsaXplQ29kZShjb2RlKTtcbiAgICBpZiAodGhpcy5yZWdpc3RlcmVkQ29kZXMuaGFzKG5vcm1hbGl6ZWQpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGdldFByb2plY3Rpb24obm9ybWFsaXplZCkgIT0gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlciBhIGN1c3RvbSBDUlMgKGUuZy4gbG9jYWwgVk4tMjAwMCkuIERlZmluaXRpb24gbXVzdCBjb21lIGZyb20gY29uZmlnL0FQSS5cbiAgICovXG4gIHJlZ2lzdGVyUHJvamVjdGlvbihjb25maWc6IFByb2plY3Rpb25Db25maWcpOiB2b2lkIHtcbiAgICBjb25zdCBjb2RlID0gdGhpcy5ub3JtYWxpemVDb2RlKGNvbmZpZy5jb2RlKTtcbiAgICBpZiAoIWNvbmZpZy5kZWZpbml0aW9uPy50cmltKCkpIHtcbiAgICAgIHRocm93IG5ldyBHZW9NYXBQcm9qZWN0aW9uRXJyb3IoXG4gICAgICAgIGBQcm9qZWN0aW9uIFwiJHtjb2RlfVwiIGlzIG1pc3NpbmcgYSBwcm9qNCBkZWZpbml0aW9uLiBTdXBwbHkgaXQgZnJvbSBlbnZpcm9ubWVudCBvciBBUEkuYCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHByb2o0LmRlZnMoY29kZSwgY29uZmlnLmRlZmluaXRpb24udHJpbSgpKTtcbiAgICAgIHJlZ2lzdGVyKHByb2o0KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnN0IGRldGFpbCA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKTtcbiAgICAgIHRocm93IG5ldyBHZW9NYXBQcm9qZWN0aW9uRXJyb3IoXG4gICAgICAgIGBJbnZhbGlkIHByb2o0IGRlZmluaXRpb24gZm9yIFwiJHtjb2RlfVwiOiAke2RldGFpbH1gLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBwcm9qZWN0aW9uID0gZ2V0UHJvamVjdGlvbihjb2RlKTtcbiAgICBpZiAoIXByb2plY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBHZW9NYXBQcm9qZWN0aW9uRXJyb3IoXG4gICAgICAgIGBPcGVuTGF5ZXJzIGRpZCBub3QgY3JlYXRlIHByb2plY3Rpb24gXCIke2NvZGV9XCIgYWZ0ZXIgcmVnaXN0cmF0aW9uLmAsXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChjb25maWcuZXh0ZW50KSB7XG4gICAgICBwcm9qZWN0aW9uLnNldEV4dGVudChjb25maWcuZXh0ZW50KTtcbiAgICB9XG5cbiAgICB0aGlzLnJlZ2lzdGVyZWRDb2Rlcy5hZGQoY29kZSk7XG4gIH1cblxuICBlbnN1cmVSZWdpc3RlcmVkKGNvZGU6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSB0aGlzLm5vcm1hbGl6ZUNvZGUoY29kZSk7XG4gICAgaWYgKCF0aGlzLmlzUmVnaXN0ZXJlZChub3JtYWxpemVkKSkge1xuICAgICAgdGhyb3cgbmV3IEdlb01hcFByb2plY3Rpb25FcnJvcihcbiAgICAgICAgYFByb2plY3Rpb24gXCIke25vcm1hbGl6ZWR9XCIgaXMgbm90IHJlZ2lzdGVyZWQuIENhbGwgcmVnaXN0ZXJQcm9qZWN0aW9uKCkgd2l0aCBhIHZhbGlkIGRlZmluaXRpb24gZmlyc3QuYCxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyYW5zZm9ybSBhIGNvb3JkaW5hdGUuIE9yZGVyIGlzIGFsd2F5cyBbeCwgeV0gLyBbbG9uZ2l0dWRlLCBsYXRpdHVkZV0uXG4gICAqL1xuICB0cmFuc2Zvcm1Db29yZGluYXRlKFxuICAgIGNvb3JkaW5hdGU6IFtudW1iZXIsIG51bWJlcl0gfCBudW1iZXJbXSxcbiAgICBmcm9tUHJvamVjdGlvbjogc3RyaW5nLFxuICAgIHRvUHJvamVjdGlvbjogc3RyaW5nLFxuICApOiBbbnVtYmVyLCBudW1iZXJdIHtcbiAgICBpZiAoY29vcmRpbmF0ZS5sZW5ndGggPCAyKSB7XG4gICAgICB0aHJvdyBuZXcgR2VvTWFwUHJvamVjdGlvbkVycm9yKCdDb29yZGluYXRlIG11c3QgaGF2ZSBhdCBsZWFzdCB0d28gdmFsdWVzIFt4LCB5XS4nKTtcbiAgICB9XG4gICAgY29uc3QgZnJvbSA9IHRoaXMubm9ybWFsaXplQ29kZShmcm9tUHJvamVjdGlvbik7XG4gICAgY29uc3QgdG8gPSB0aGlzLm5vcm1hbGl6ZUNvZGUodG9Qcm9qZWN0aW9uKTtcbiAgICB0aGlzLmVuc3VyZVJlZ2lzdGVyZWQoZnJvbSk7XG4gICAgdGhpcy5lbnN1cmVSZWdpc3RlcmVkKHRvKTtcblxuICAgIGlmIChmcm9tID09PSB0bykge1xuICAgICAgcmV0dXJuIFtOdW1iZXIoY29vcmRpbmF0ZVswXSksIE51bWJlcihjb29yZGluYXRlWzFdKV07XG4gICAgfVxuXG4gICAgY29uc3QgcmVzdWx0ID0gdHJhbnNmb3JtKFxuICAgICAgW051bWJlcihjb29yZGluYXRlWzBdKSwgTnVtYmVyKGNvb3JkaW5hdGVbMV0pXSxcbiAgICAgIGZyb20sXG4gICAgICB0byxcbiAgICApO1xuICAgIHJldHVybiBbcmVzdWx0WzBdLCByZXN1bHRbMV1dO1xuICB9XG5cbiAgdHJhbnNmb3JtRXh0ZW50KFxuICAgIGV4dGVudDogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gICAgZnJvbVByb2plY3Rpb246IHN0cmluZyxcbiAgICB0b1Byb2plY3Rpb246IHN0cmluZyxcbiAgKTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0ge1xuICAgIGNvbnN0IGZyb20gPSB0aGlzLm5vcm1hbGl6ZUNvZGUoZnJvbVByb2plY3Rpb24pO1xuICAgIGNvbnN0IHRvID0gdGhpcy5ub3JtYWxpemVDb2RlKHRvUHJvamVjdGlvbik7XG4gICAgdGhpcy5lbnN1cmVSZWdpc3RlcmVkKGZyb20pO1xuICAgIHRoaXMuZW5zdXJlUmVnaXN0ZXJlZCh0byk7XG5cbiAgICBpZiAoZnJvbSA9PT0gdG8pIHtcbiAgICAgIHJldHVybiBbLi4uZXh0ZW50XTtcbiAgICB9XG5cbiAgICBjb25zdCByZXN1bHQgPSB0cmFuc2Zvcm1FeHRlbnQoZXh0ZW50LCBmcm9tLCB0byk7XG4gICAgcmV0dXJuIFtyZXN1bHRbMF0sIHJlc3VsdFsxXSwgcmVzdWx0WzJdLCByZXN1bHRbM11dO1xuICB9XG5cbiAgLyoqXG4gICAqIE5vcm1hbGl6ZSB1c2VyIGlucHV0OiB0cmltLCB1cHBlci1jYXNlIEVQU0cgY29kZXMsIHJlamVjdCBub24tZmluaXRlIG51bWJlcnMuXG4gICAqL1xuICBub3JtYWxpemVDb29yZGluYXRlKFxuICAgIHZhbHVlOiB1bmtub3duLFxuICAgIG9wdGlvbnM/OiB7IGxhYmVsPzogc3RyaW5nIH0sXG4gICk6IFtudW1iZXIsIG51bWJlcl0ge1xuICAgIGNvbnN0IGxhYmVsID0gb3B0aW9ucz8ubGFiZWwgPz8gJ2Nvb3JkaW5hdGUnO1xuICAgIGlmICghQXJyYXkuaXNBcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgdGhyb3cgbmV3IEdlb01hcFByb2plY3Rpb25FcnJvcihcbiAgICAgICAgYEludmFsaWQgJHtsYWJlbH06IGV4cGVjdGVkIFt4LCB5XSBvciBbbG9uZ2l0dWRlLCBsYXRpdHVkZV0uYCxcbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnN0IHggPSBOdW1iZXIodmFsdWVbMF0pO1xuICAgIGNvbnN0IHkgPSBOdW1iZXIodmFsdWVbMV0pO1xuICAgIGlmICghTnVtYmVyLmlzRmluaXRlKHgpIHx8ICFOdW1iZXIuaXNGaW5pdGUoeSkpIHtcbiAgICAgIHRocm93IG5ldyBHZW9NYXBQcm9qZWN0aW9uRXJyb3IoYEludmFsaWQgJHtsYWJlbH06IHZhbHVlcyBtdXN0IGJlIGZpbml0ZSBudW1iZXJzLmApO1xuICAgIH1cbiAgICByZXR1cm4gW3gsIHldO1xuICB9XG5cbiAgbm9ybWFsaXplQ29kZShjb2RlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBjb2RlLnRyaW0oKTtcbiAgfVxufVxuIl19