@kalisio/kdk 2.6.3 → 2.7.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 (419) hide show
  1. package/core/api/application.js +2 -4
  2. package/core/api/authentication.js +2 -3
  3. package/core/api/db.js +10 -2
  4. package/core/api/hooks/hooks.authorisations.js +4 -2
  5. package/core/api/hooks/hooks.push.js +6 -2
  6. package/core/api/hooks/hooks.query.js +29 -12
  7. package/core/api/hooks/hooks.users.js +30 -17
  8. package/core/api/models/configurations.model.mongodb.js +4 -0
  9. package/core/api/services/authorisations/authorisations.service.js +1 -1
  10. package/core/api/services/configurations/configurations.hooks.js +33 -0
  11. package/core/api/services/index.js +41 -7
  12. package/core/api/services/messages/messages.hooks.js +9 -3
  13. package/core/client/api.js +14 -1
  14. package/core/client/capabilities.js +1 -6
  15. package/core/client/components/KAvatar.vue +24 -20
  16. package/core/client/components/account/KProfile.vue +10 -71
  17. package/core/client/components/account/index.js +0 -2
  18. package/core/client/components/app/KSettings.vue +1 -0
  19. package/core/client/components/collection/KBoard.vue +4 -3
  20. package/core/client/components/collection/KCardSection.vue +1 -0
  21. package/core/client/components/collection/KGrid.vue +2 -0
  22. package/core/client/components/collection/KTable.vue +5 -1
  23. package/core/client/components/collection/KTimeLine.vue +9 -1
  24. package/core/client/components/collection/index.js +0 -2
  25. package/core/client/components/form/KChipsField.vue +2 -1
  26. package/core/client/components/form/KEmailField.vue +1 -0
  27. package/core/client/components/form/KFileField.vue +22 -1
  28. package/core/client/components/form/KForm.vue +2 -0
  29. package/core/client/components/form/KItemField.vue +1 -0
  30. package/core/client/components/form/KNumberField.vue +1 -0
  31. package/core/client/components/form/KPasswordField.vue +1 -0
  32. package/core/client/components/form/KPhoneField.vue +1 -0
  33. package/core/client/components/form/KPropertyItemField.vue +1 -0
  34. package/core/client/components/form/KResolutionField.vue +1 -0
  35. package/core/client/components/form/KSelectField.vue +31 -0
  36. package/core/client/components/form/KTagField.vue +1 -0
  37. package/core/client/components/form/KTextField.vue +1 -0
  38. package/core/client/components/form/KTokenField.vue +1 -0
  39. package/core/client/components/form/KUnitField.vue +1 -0
  40. package/core/client/components/form/KUrlField.vue +1 -0
  41. package/core/client/components/graphics/KIcon.vue +3 -4
  42. package/core/client/components/layout/KPage.vue +1 -0
  43. package/core/client/components/layout/KWindow.vue +6 -3
  44. package/core/client/components/messages/KMessageComposer.vue +2 -1
  45. package/core/client/components/messages/KMessagesTimeLine.vue +1 -1
  46. package/core/client/components/time/KDate.vue +1 -2
  47. package/core/client/components/time/KDateTime.vue +11 -11
  48. package/core/client/components/time/KTime.vue +1 -1
  49. package/core/client/composables/collection.js +33 -8
  50. package/core/client/composables/errors.js +1 -1
  51. package/core/client/composables/layout.js +9 -9
  52. package/core/client/configurations.js +50 -0
  53. package/core/client/exporter.js +1 -1
  54. package/core/client/i18n/core_en.json +6 -39
  55. package/core/client/i18n/core_fr.json +6 -39
  56. package/core/client/index.js +2 -0
  57. package/core/client/layout.js +8 -8
  58. package/core/client/mixins/mixin.base-activity.js +5 -2
  59. package/core/client/mixins/mixin.base-field.js +3 -3
  60. package/core/client/search.js +2 -1
  61. package/core/client/utils/utils.collection.js +8 -8
  62. package/core/client/utils/utils.items.js +4 -0
  63. package/core/client/utils/utils.push.js +3 -3
  64. package/core/client/utils/utils.session.js +7 -5
  65. package/core/client/utils/utils.shapes.js +38 -7
  66. package/core/client/utils/utils.time.js +21 -22
  67. package/core/common/schemas/users.update-profile.json +3 -2
  68. package/coverage/core/api/application.js.html +1 -1
  69. package/coverage/core/api/authentication.js.html +1 -1
  70. package/coverage/core/api/db.js.html +1 -1
  71. package/coverage/core/api/hooks/hooks.authentication.js.html +1 -1
  72. package/coverage/core/api/hooks/hooks.authorisations.js.html +1 -1
  73. package/coverage/core/api/hooks/hooks.logger.js.html +1 -1
  74. package/coverage/core/api/hooks/hooks.model.js.html +1 -1
  75. package/coverage/core/api/hooks/hooks.push.js.html +22 -10
  76. package/coverage/core/api/hooks/hooks.query.js.html +33 -6
  77. package/coverage/core/api/hooks/hooks.schemas.js.html +1 -1
  78. package/coverage/core/api/hooks/hooks.service.js.html +1 -1
  79. package/coverage/core/api/hooks/hooks.storage.js.html +1 -1
  80. package/coverage/core/api/hooks/hooks.tags.js.html +1 -1
  81. package/coverage/core/api/hooks/hooks.users.js.html +4 -4
  82. package/coverage/core/api/hooks/index.html +23 -23
  83. package/coverage/core/api/hooks/index.js.html +1 -1
  84. package/coverage/core/api/index.html +1 -1
  85. package/coverage/core/api/index.js.html +1 -1
  86. package/coverage/core/api/marshall.js.html +1 -1
  87. package/coverage/core/api/models/configurations.model.mongodb.js.html +1 -1
  88. package/coverage/core/api/models/index.html +1 -1
  89. package/coverage/core/api/models/messages.model.mongodb.js.html +1 -1
  90. package/coverage/core/api/models/tags.model.mongodb.js.html +1 -1
  91. package/coverage/core/api/models/users.model.mongodb.js.html +1 -1
  92. package/coverage/core/api/services/account/account.hooks.js.html +1 -1
  93. package/coverage/core/api/services/account/account.service.js.html +1 -1
  94. package/coverage/core/api/services/account/index.html +1 -1
  95. package/coverage/core/api/services/authorisations/authorisations.hooks.js.html +1 -1
  96. package/coverage/core/api/services/authorisations/authorisations.service.js.html +1 -1
  97. package/coverage/core/api/services/authorisations/index.html +1 -1
  98. package/coverage/core/api/services/configurations/configurations.hooks.js.html +1 -1
  99. package/coverage/core/api/services/configurations/index.html +1 -1
  100. package/coverage/core/api/services/databases/databases.hooks.js.html +1 -1
  101. package/coverage/core/api/services/databases/databases.service.js.html +1 -1
  102. package/coverage/core/api/services/databases/index.html +1 -1
  103. package/coverage/core/api/services/import-export/import-export.hooks.js.html +1 -1
  104. package/coverage/core/api/services/import-export/import-export.service.js.html +1 -1
  105. package/coverage/core/api/services/import-export/index.html +1 -1
  106. package/coverage/core/api/services/index.html +1 -1
  107. package/coverage/core/api/services/index.js.html +1 -1
  108. package/coverage/core/api/services/mailer/index.html +1 -1
  109. package/coverage/core/api/services/mailer/mailer.hooks.js.html +1 -1
  110. package/coverage/core/api/services/mailer/mailer.service.js.html +1 -1
  111. package/coverage/core/api/services/messages/index.html +1 -1
  112. package/coverage/core/api/services/messages/messages.hooks.js.html +1 -1
  113. package/coverage/core/api/services/push/index.html +1 -1
  114. package/coverage/core/api/services/push/push.hooks.js.html +1 -1
  115. package/coverage/core/api/services/push/push.service.js.html +1 -1
  116. package/coverage/core/api/services/storage/index.html +1 -1
  117. package/coverage/core/api/services/storage/storage.hooks.js.html +1 -1
  118. package/coverage/core/api/services/storage/storage.service.js.html +1 -1
  119. package/coverage/core/api/services/tags/index.html +1 -1
  120. package/coverage/core/api/services/tags/tags.hooks.js.html +1 -1
  121. package/coverage/core/api/services/users/index.html +1 -1
  122. package/coverage/core/api/services/users/users.hooks.js.html +1 -1
  123. package/coverage/core/api/services/users/users.service.js.html +1 -1
  124. package/coverage/core/common/errors.js.html +1 -1
  125. package/coverage/core/common/index.html +1 -1
  126. package/coverage/core/common/index.js.html +1 -1
  127. package/coverage/core/common/permissions.js.html +1 -1
  128. package/coverage/core/common/schema.js.html +1 -1
  129. package/coverage/core/common/utils.js.html +1 -1
  130. package/coverage/core/common/utils.offline.js.html +1 -1
  131. package/coverage/index.html +17 -17
  132. package/coverage/lcov-report/core/api/application.js.html +1 -1
  133. package/coverage/lcov-report/core/api/authentication.js.html +1 -1
  134. package/coverage/lcov-report/core/api/db.js.html +1 -1
  135. package/coverage/lcov-report/core/api/hooks/hooks.authentication.js.html +1 -1
  136. package/coverage/lcov-report/core/api/hooks/hooks.authorisations.js.html +1 -1
  137. package/coverage/lcov-report/core/api/hooks/hooks.logger.js.html +1 -1
  138. package/coverage/lcov-report/core/api/hooks/hooks.model.js.html +1 -1
  139. package/coverage/lcov-report/core/api/hooks/hooks.push.js.html +22 -10
  140. package/coverage/lcov-report/core/api/hooks/hooks.query.js.html +33 -6
  141. package/coverage/lcov-report/core/api/hooks/hooks.schemas.js.html +1 -1
  142. package/coverage/lcov-report/core/api/hooks/hooks.service.js.html +1 -1
  143. package/coverage/lcov-report/core/api/hooks/hooks.storage.js.html +1 -1
  144. package/coverage/lcov-report/core/api/hooks/hooks.tags.js.html +1 -1
  145. package/coverage/lcov-report/core/api/hooks/hooks.users.js.html +4 -4
  146. package/coverage/lcov-report/core/api/hooks/index.html +23 -23
  147. package/coverage/lcov-report/core/api/hooks/index.js.html +1 -1
  148. package/coverage/lcov-report/core/api/index.html +1 -1
  149. package/coverage/lcov-report/core/api/index.js.html +1 -1
  150. package/coverage/lcov-report/core/api/marshall.js.html +1 -1
  151. package/coverage/lcov-report/core/api/models/configurations.model.mongodb.js.html +1 -1
  152. package/coverage/lcov-report/core/api/models/index.html +1 -1
  153. package/coverage/lcov-report/core/api/models/messages.model.mongodb.js.html +1 -1
  154. package/coverage/lcov-report/core/api/models/tags.model.mongodb.js.html +1 -1
  155. package/coverage/lcov-report/core/api/models/users.model.mongodb.js.html +1 -1
  156. package/coverage/lcov-report/core/api/services/account/account.hooks.js.html +1 -1
  157. package/coverage/lcov-report/core/api/services/account/account.service.js.html +1 -1
  158. package/coverage/lcov-report/core/api/services/account/index.html +1 -1
  159. package/coverage/lcov-report/core/api/services/authorisations/authorisations.hooks.js.html +1 -1
  160. package/coverage/lcov-report/core/api/services/authorisations/authorisations.service.js.html +1 -1
  161. package/coverage/lcov-report/core/api/services/authorisations/index.html +1 -1
  162. package/coverage/lcov-report/core/api/services/configurations/configurations.hooks.js.html +1 -1
  163. package/coverage/lcov-report/core/api/services/configurations/index.html +1 -1
  164. package/coverage/lcov-report/core/api/services/databases/databases.hooks.js.html +1 -1
  165. package/coverage/lcov-report/core/api/services/databases/databases.service.js.html +1 -1
  166. package/coverage/lcov-report/core/api/services/databases/index.html +1 -1
  167. package/coverage/lcov-report/core/api/services/import-export/import-export.hooks.js.html +1 -1
  168. package/coverage/lcov-report/core/api/services/import-export/import-export.service.js.html +1 -1
  169. package/coverage/lcov-report/core/api/services/import-export/index.html +1 -1
  170. package/coverage/lcov-report/core/api/services/index.html +1 -1
  171. package/coverage/lcov-report/core/api/services/index.js.html +1 -1
  172. package/coverage/lcov-report/core/api/services/mailer/index.html +1 -1
  173. package/coverage/lcov-report/core/api/services/mailer/mailer.hooks.js.html +1 -1
  174. package/coverage/lcov-report/core/api/services/mailer/mailer.service.js.html +1 -1
  175. package/coverage/lcov-report/core/api/services/messages/index.html +1 -1
  176. package/coverage/lcov-report/core/api/services/messages/messages.hooks.js.html +1 -1
  177. package/coverage/lcov-report/core/api/services/push/index.html +1 -1
  178. package/coverage/lcov-report/core/api/services/push/push.hooks.js.html +1 -1
  179. package/coverage/lcov-report/core/api/services/push/push.service.js.html +1 -1
  180. package/coverage/lcov-report/core/api/services/storage/index.html +1 -1
  181. package/coverage/lcov-report/core/api/services/storage/storage.hooks.js.html +1 -1
  182. package/coverage/lcov-report/core/api/services/storage/storage.service.js.html +1 -1
  183. package/coverage/lcov-report/core/api/services/tags/index.html +1 -1
  184. package/coverage/lcov-report/core/api/services/tags/tags.hooks.js.html +1 -1
  185. package/coverage/lcov-report/core/api/services/users/index.html +1 -1
  186. package/coverage/lcov-report/core/api/services/users/users.hooks.js.html +1 -1
  187. package/coverage/lcov-report/core/api/services/users/users.service.js.html +1 -1
  188. package/coverage/lcov-report/core/common/errors.js.html +1 -1
  189. package/coverage/lcov-report/core/common/index.html +1 -1
  190. package/coverage/lcov-report/core/common/index.js.html +1 -1
  191. package/coverage/lcov-report/core/common/permissions.js.html +1 -1
  192. package/coverage/lcov-report/core/common/schema.js.html +1 -1
  193. package/coverage/lcov-report/core/common/utils.js.html +1 -1
  194. package/coverage/lcov-report/core/common/utils.offline.js.html +1 -1
  195. package/coverage/lcov-report/index.html +17 -17
  196. package/coverage/lcov-report/map/api/hooks/hooks.catalog.js.html +1 -1
  197. package/coverage/lcov-report/map/api/hooks/hooks.features.js.html +1 -1
  198. package/coverage/lcov-report/map/api/hooks/hooks.query.js.html +184 -4
  199. package/coverage/lcov-report/map/api/hooks/index.html +5 -5
  200. package/coverage/lcov-report/map/api/hooks/index.js.html +1 -1
  201. package/coverage/lcov-report/map/api/index.html +1 -1
  202. package/coverage/lcov-report/map/api/index.js.html +1 -1
  203. package/coverage/lcov-report/map/api/marshall.js.html +1 -1
  204. package/coverage/lcov-report/map/api/models/alerts.model.mongodb.js.html +1 -1
  205. package/coverage/lcov-report/map/api/models/catalog.model.mongodb.js.html +1 -1
  206. package/coverage/lcov-report/map/api/models/features.model.mongodb.js.html +1 -1
  207. package/coverage/lcov-report/map/api/models/index.html +1 -1
  208. package/coverage/lcov-report/map/api/models/projects.model.mongodb.js.html +1 -1
  209. package/coverage/lcov-report/map/api/models/styles.model.mongodb.js.html +1 -1
  210. package/coverage/lcov-report/map/api/services/alerts/alerts.hooks.js.html +1 -1
  211. package/coverage/lcov-report/map/api/services/alerts/alerts.service.js.html +1 -1
  212. package/coverage/lcov-report/map/api/services/alerts/index.html +1 -1
  213. package/coverage/lcov-report/map/api/services/catalog/catalog.hooks.js.html +1 -1
  214. package/coverage/lcov-report/map/api/services/catalog/index.html +1 -1
  215. package/coverage/lcov-report/map/api/services/daptiles/daptiles.service.js.html +1 -1
  216. package/coverage/lcov-report/map/api/services/daptiles/index.html +1 -1
  217. package/coverage/lcov-report/map/api/services/features/features.hooks.js.html +1 -1
  218. package/coverage/lcov-report/map/api/services/features/features.service.js.html +1 -1
  219. package/coverage/lcov-report/map/api/services/features/index.html +1 -1
  220. package/coverage/lcov-report/map/api/services/index.html +1 -1
  221. package/coverage/lcov-report/map/api/services/index.js.html +1 -1
  222. package/coverage/lcov-report/map/api/services/projects/index.html +1 -1
  223. package/coverage/lcov-report/map/api/services/projects/projects.hooks.js.html +1 -1
  224. package/coverage/lcov-report/map/api/services/styles/index.html +1 -1
  225. package/coverage/lcov-report/map/api/services/styles/styles.hooks.js.html +1 -1
  226. package/coverage/lcov-report/map/common/dynamic-grid-source.js.html +1 -1
  227. package/coverage/lcov-report/map/common/errors.js.html +1 -1
  228. package/coverage/lcov-report/map/common/geotiff-grid-source.js.html +1 -1
  229. package/coverage/lcov-report/map/common/grid.js.html +1 -1
  230. package/coverage/lcov-report/map/common/index.html +1 -1
  231. package/coverage/lcov-report/map/common/index.js.html +1 -1
  232. package/coverage/lcov-report/map/common/meteo-model-grid-source.js.html +1 -1
  233. package/coverage/lcov-report/map/common/moment-utils.js.html +1 -1
  234. package/coverage/lcov-report/map/common/opendap-grid-source.js.html +1 -1
  235. package/coverage/lcov-report/map/common/opendap-utils.js.html +1 -1
  236. package/coverage/lcov-report/map/common/permissions.js.html +1 -1
  237. package/coverage/lcov-report/map/common/time-based-grid-source.js.html +1 -1
  238. package/coverage/lcov-report/map/common/tms-utils.js.html +1 -1
  239. package/coverage/lcov-report/map/common/wcs-grid-source.js.html +1 -1
  240. package/coverage/lcov-report/map/common/wcs-utils.js.html +1 -1
  241. package/coverage/lcov-report/map/common/weacast-grid-source.js.html +1 -1
  242. package/coverage/lcov-report/map/common/wfs-utils.js.html +1 -1
  243. package/coverage/lcov-report/map/common/wms-utils.js.html +1 -1
  244. package/coverage/lcov-report/map/common/wmts-utils.js.html +1 -1
  245. package/coverage/lcov.info +358 -280
  246. package/coverage/map/api/hooks/hooks.catalog.js.html +1 -1
  247. package/coverage/map/api/hooks/hooks.features.js.html +1 -1
  248. package/coverage/map/api/hooks/hooks.query.js.html +184 -4
  249. package/coverage/map/api/hooks/index.html +5 -5
  250. package/coverage/map/api/hooks/index.js.html +1 -1
  251. package/coverage/map/api/index.html +1 -1
  252. package/coverage/map/api/index.js.html +1 -1
  253. package/coverage/map/api/marshall.js.html +1 -1
  254. package/coverage/map/api/models/alerts.model.mongodb.js.html +1 -1
  255. package/coverage/map/api/models/catalog.model.mongodb.js.html +1 -1
  256. package/coverage/map/api/models/features.model.mongodb.js.html +1 -1
  257. package/coverage/map/api/models/index.html +1 -1
  258. package/coverage/map/api/models/projects.model.mongodb.js.html +1 -1
  259. package/coverage/map/api/models/styles.model.mongodb.js.html +1 -1
  260. package/coverage/map/api/services/alerts/alerts.hooks.js.html +1 -1
  261. package/coverage/map/api/services/alerts/alerts.service.js.html +1 -1
  262. package/coverage/map/api/services/alerts/index.html +1 -1
  263. package/coverage/map/api/services/catalog/catalog.hooks.js.html +1 -1
  264. package/coverage/map/api/services/catalog/index.html +1 -1
  265. package/coverage/map/api/services/daptiles/daptiles.service.js.html +1 -1
  266. package/coverage/map/api/services/daptiles/index.html +1 -1
  267. package/coverage/map/api/services/features/features.hooks.js.html +1 -1
  268. package/coverage/map/api/services/features/features.service.js.html +1 -1
  269. package/coverage/map/api/services/features/index.html +1 -1
  270. package/coverage/map/api/services/index.html +1 -1
  271. package/coverage/map/api/services/index.js.html +1 -1
  272. package/coverage/map/api/services/projects/index.html +1 -1
  273. package/coverage/map/api/services/projects/projects.hooks.js.html +1 -1
  274. package/coverage/map/api/services/styles/index.html +1 -1
  275. package/coverage/map/api/services/styles/styles.hooks.js.html +1 -1
  276. package/coverage/map/common/dynamic-grid-source.js.html +1 -1
  277. package/coverage/map/common/errors.js.html +1 -1
  278. package/coverage/map/common/geotiff-grid-source.js.html +1 -1
  279. package/coverage/map/common/grid.js.html +1 -1
  280. package/coverage/map/common/index.html +1 -1
  281. package/coverage/map/common/index.js.html +1 -1
  282. package/coverage/map/common/meteo-model-grid-source.js.html +1 -1
  283. package/coverage/map/common/moment-utils.js.html +1 -1
  284. package/coverage/map/common/opendap-grid-source.js.html +1 -1
  285. package/coverage/map/common/opendap-utils.js.html +1 -1
  286. package/coverage/map/common/permissions.js.html +1 -1
  287. package/coverage/map/common/time-based-grid-source.js.html +1 -1
  288. package/coverage/map/common/tms-utils.js.html +1 -1
  289. package/coverage/map/common/wcs-grid-source.js.html +1 -1
  290. package/coverage/map/common/wcs-utils.js.html +1 -1
  291. package/coverage/map/common/weacast-grid-source.js.html +1 -1
  292. package/coverage/map/common/wfs-utils.js.html +1 -1
  293. package/coverage/map/common/wms-utils.js.html +1 -1
  294. package/coverage/map/common/wmts-utils.js.html +1 -1
  295. package/coverage/tmp/coverage-1028514-1773134124472-0.json +1 -0
  296. package/coverage/tmp/coverage-1028526-1773134124448-0.json +1 -0
  297. package/coverage/tmp/coverage-1028537-1773134124431-0.json +1 -0
  298. package/coverage/tmp/coverage-1028549-1773134124401-0.json +1 -0
  299. package/coverage/tmp/{coverage-222566-1765963609278-0.json → coverage-1028556-1773134124353-0.json} +1 -1
  300. package/extras/configs/widgets.top.js +3 -3
  301. package/extras/tests/core/collection.mjs +2 -9
  302. package/map/api/hooks/hooks.catalog.js +18 -4
  303. package/map/api/services/catalog/catalog.hooks.js +3 -0
  304. package/map/api/services/features/features.hooks.js +3 -1
  305. package/map/api/services/index.js +2 -6
  306. package/map/api/services/styles/styles.hooks.js +6 -1
  307. package/map/client/components/KFeatureActionButton.vue +9 -3
  308. package/map/client/components/KFeaturesFilterManager.vue +5 -5
  309. package/map/client/components/KFilterCondition.vue +17 -10
  310. package/map/client/components/KLayerEditor.vue +49 -39
  311. package/map/client/components/KMeasureTool.vue +7 -1
  312. package/map/client/components/KTimezoneMap.vue +29 -9
  313. package/map/client/components/catalog/KLayersPanel.vue +26 -16
  314. package/map/client/components/catalog/KLayersSelector.vue +13 -2
  315. package/map/client/components/catalog/KViewsPanel.vue +5 -4
  316. package/map/client/components/form/KSelectLayersField.vue +28 -17
  317. package/map/client/components/form/KSelectViewsField.vue +18 -9
  318. package/map/client/components/form/KTimezoneField.vue +1 -2
  319. package/map/client/components/legend/KVariablesLegend.vue +10 -1
  320. package/map/client/components/location/KLocationCardSection.vue +7 -2
  321. package/map/client/components/location/KLocationMap.vue +31 -7
  322. package/map/client/components/selection/KSelectedLayerFeatures.vue +2 -2
  323. package/map/client/components/stickies/KZoomControl.vue +1 -1
  324. package/map/client/components/styles/KStyleManager.vue +4 -1
  325. package/map/client/components/widget/KTimeSeries.vue +174 -497
  326. package/map/client/components/widget/KTimeSeriesSelector.vue +72 -0
  327. package/map/client/components/widget/KTimeSeriesToolbar.vue +83 -0
  328. package/map/client/composables/catalog.js +6 -10
  329. package/map/client/composables/highlight.js +12 -9
  330. package/map/client/composables/project.js +1 -1
  331. package/map/client/composables/selection.js +8 -7
  332. package/map/client/composables/weather.js +9 -2
  333. package/map/client/geolocation.js +8 -5
  334. package/map/client/i18n/map_en.json +10 -8
  335. package/map/client/i18n/map_fr.json +9 -7
  336. package/map/client/leaflet/TiledFeatureLayer.js +85 -82
  337. package/map/client/leaflet/utils/utils.geojson.js +3 -3
  338. package/map/client/mixins/globe/mixin.base-globe.js +15 -6
  339. package/map/client/mixins/globe/mixin.geojson-layers.js +27 -18
  340. package/map/client/mixins/map/mixin.edit-layers.js +9 -1
  341. package/map/client/mixins/map/mixin.pmtiles-layers.js +118 -29
  342. package/map/client/mixins/map/mixin.tiled-mesh-layers.js +12 -5
  343. package/map/client/mixins/map/mixin.tiled-wind-layers.js +19 -10
  344. package/map/client/mixins/mixin.activity.js +23 -30
  345. package/map/client/mixins/mixin.feature-selection.js +41 -5
  346. package/map/client/planets.js +1 -1
  347. package/map/client/readers/reader.kml.js +2 -3
  348. package/map/client/utils/utils.catalog.js +36 -10
  349. package/map/client/utils/utils.layers.js +39 -8
  350. package/map/client/utils/utils.project.js +4 -0
  351. package/map/client/utils/utils.style.js +37 -7
  352. package/map/client/utils/utils.time-series.js +215 -6
  353. package/map/common/schemas/catalog.update.json +1 -1
  354. package/map/common/weacast-grid-source.js +1 -1
  355. package/package.json +3 -3
  356. package/scripts/kash/CHANGELOG.md +0 -4
  357. package/scripts/kash/README.md +0 -9
  358. package/scripts/kash/kash.sh +45 -40
  359. package/scripts/kash/scripts/run_tests.sh +1 -4
  360. package/test/api/core/authentication.test.js +9 -4
  361. package/test/api/core/config/default.cjs +1 -0
  362. package/test/api/core/hooks.test.js +6 -0
  363. package/test/api/core/index.test.js +43 -18
  364. package/test/api/core/push.test.js +8 -8
  365. package/test/api/core/test-log-2026-03-10.log +60 -0
  366. package/test/api/core/users.test.js +384 -0
  367. package/test/api/map/grid-sources.test.js +1 -1
  368. package/test/api/map/test-log-2026-03-10.log +56 -0
  369. package/vite/package.json +11 -2
  370. package/vite/test/core/composables.test.js +77 -0
  371. package/vite/vitest.config.js +13 -0
  372. package/vite/yarn.lock +1096 -18
  373. package/client/css/core.variables.scss +0 -72
  374. package/client/i18n/core_en.json +0 -744
  375. package/client/i18n/core_fr.json +0 -744
  376. package/client/i18n/map_en.json +0 -800
  377. package/client/i18n/map_fr.json +0 -800
  378. package/client/kdk.client.css +0 -47
  379. package/client/kdk.client.js +0 -41097
  380. package/client/kdk.client.map.css +0 -47
  381. package/client/kdk.client.map.js +0 -38182
  382. package/client/kdk.client.map.min.css +0 -1
  383. package/client/kdk.client.map.min.js +0 -27032
  384. package/client/kdk.client.min.css +0 -1
  385. package/client/kdk.client.min.js +0 -29074
  386. package/client/schemas/capture.create.json +0 -132
  387. package/client/schemas/catalog.update.json +0 -44
  388. package/client/schemas/messages.update.json +0 -16
  389. package/client/schemas/projects.create.json +0 -52
  390. package/client/schemas/projects.update.json +0 -52
  391. package/client/schemas/settings.update.json +0 -286
  392. package/client/schemas/tags.update.json +0 -35
  393. package/client/schemas/users.update-profile.json +0 -34
  394. package/core/client/components/account/KAccount.vue +0 -68
  395. package/core/client/components/account/KDeleteAccountManager.vue +0 -62
  396. package/core/client/components/account/KEmailManager.vue +0 -128
  397. package/core/client/components/account/KPasswordManager.vue +0 -90
  398. package/core/client/components/account/KVerifyEmailManager.vue +0 -105
  399. package/core/client/components/collection/KColumn.vue +0 -227
  400. package/core/client/components/collection/KHistory.vue +0 -113
  401. package/core/client/components/collection/KHistoryEntry.vue +0 -109
  402. package/coverage/tmp/coverage-222524-1765963609350-0.json +0 -1
  403. package/coverage/tmp/coverage-222536-1765963609335-0.json +0 -1
  404. package/coverage/tmp/coverage-222547-1765963609324-0.json +0 -1
  405. package/coverage/tmp/coverage-222559-1765963609309-0.json +0 -1
  406. package/scripts/kash/LICENSE +0 -21
  407. package/test/api/core/test-log-2025-07-31.log +0 -15
  408. package/test/api/core/test-log-2025-10-03.log +0 -18
  409. package/test/api/core/test-log-2025-11-10.log +0 -0
  410. package/test/api/core/test-log-2025-11-12.log +0 -117
  411. package/test/api/core/test-log-2025-11-27.log +0 -0
  412. package/test/api/core/test-log-2025-11-28.log +0 -17
  413. package/test/api/core/test-log-2025-12-09.log +0 -148
  414. package/test/api/core/test-log-2025-12-17.log +0 -58
  415. package/test/api/core/test-log-2026-01-29.log +0 -17
  416. package/test/api/map/test-log-2025-07-23.log +0 -1
  417. package/test/api/map/test-log-2025-11-28.log +0 -33
  418. package/test/api/map/test-log-2025-12-10.log +0 -2
  419. package/test/api/map/test-log-2026-01-06.log +0 -26
@@ -0,0 +1,384 @@
1
+ import _ from 'lodash'
2
+ import authentication from '@feathersjs/authentication'
3
+ import commonHooks from 'feathers-hooks-common'
4
+ import request from 'superagent'
5
+ import chai from 'chai'
6
+ import chailint from 'chai-lint'
7
+ import core, { kdk, hooks } from '../../../core/api/index.js'
8
+
9
+ const { authenticate } = authentication.hooks
10
+ const { util, expect } = chai
11
+ const { iff, disallow, isProvider, keep, discard } = commonHooks
12
+ const { isNotMe, onlyMe, preventChanges } = hooks
13
+
14
+ describe('core:users', () => {
15
+ let app, server, port, baseUrl, userIdAccessToken, emailAccessToken, phoneAccessToken, statelessAccessToken, adminAccessToken,
16
+ userService, userObject, anotherUserObject, authenticationService
17
+
18
+ before(async () => {
19
+ chailint(chai, util)
20
+
21
+ app = kdk()
22
+ port = app.get('port')
23
+ baseUrl = `http://localhost:${port}${app.get('apiPath')}`
24
+ await app.db.connect()
25
+ await app.db.instance.dropDatabase()
26
+ })
27
+
28
+ it('registers the services', async () => {
29
+ await app.configure(core)
30
+ authenticationService = app.getService('authentication')
31
+ expect(authenticationService).toExist()
32
+ userService = app.getService('users')
33
+ expect(userService).toExist()
34
+ // Register hooks, what we'd like is a configuration so that:
35
+ // - information disclosure about internal user secrets like password is not permitted
36
+ // - information disclosure about others users is not permitted for a given user unless it has 'administrator' permissions
37
+ // - privilege escalation is not permitted for a given user
38
+ // - user with 'administrator' permissions can change others user permissions
39
+ // - changing others users information is not permitted for a given user unless it has 'administrator' permissions
40
+ // - external calls can only target myself except if I have administrator permissions
41
+ const isNotAdministrator = (context) => {
42
+ const userPermissions = _.get(context.params, 'user.permissions')
43
+ return userPermissions !== 'administrator'
44
+ }
45
+ userService.hooks({
46
+ before: {
47
+ all: authenticate('jwt'),
48
+ get: [iff(isNotMe(), disallow('external'))],
49
+ find: [iff(isProvider('external'), iff(isNotAdministrator, onlyMe()))],
50
+ create: [iff(isProvider('external'), keep('name', 'email', 'profile', 'password'))],
51
+ update: [disallow('external')],
52
+ patch: [iff(isProvider('external'), iff(isNotAdministrator, onlyMe(), preventChanges(true, ['permissions'])))],
53
+ remove: [iff(isProvider('external'), iff(isNotAdministrator, onlyMe()))]
54
+ },
55
+ after: {
56
+ all: [iff(isProvider('external'), iff(isNotMe(), iff(isNotAdministrator, discard('permissions'))))]
57
+ }
58
+ })
59
+ // Now app is configured launch the server
60
+ server = await app.listen(port)
61
+ await new Promise(resolve => server.once('listening', resolve))
62
+ })
63
+ // Let enough time to process
64
+ .timeout(10000)
65
+
66
+ it('creates users and tokens with different subject identifiers', async () => {
67
+ userObject = await userService.create({
68
+ email: 'test@test.org',
69
+ name: 'test user',
70
+ permissions: 'user',
71
+ profile: { phone: '0623256968' }
72
+ })
73
+ userIdAccessToken = await authenticationService.createAccessToken({
74
+ sub: userObject._id
75
+ })
76
+ emailAccessToken = await authenticationService.createAccessToken({
77
+ sub: userObject.email
78
+ })
79
+ phoneAccessToken = await authenticationService.createAccessToken({
80
+ sub: userObject.profile.phone
81
+ })
82
+ statelessAccessToken = await authenticationService.createAccessToken({
83
+ property: 'mycustomproperty'
84
+ }, {
85
+ subject: 'mycustomapp'
86
+ })
87
+ anotherUserObject = await userService.create({
88
+ email: 'another_test@test.org',
89
+ name: 'another test user',
90
+ permissions: 'administrator',
91
+ profile: { phone: '0623256969' }
92
+ })
93
+ adminAccessToken = await authenticationService.createAccessToken({
94
+ sub: anotherUserObject._id
95
+ })
96
+ })
97
+
98
+ it('checks all user tokens are recognized', async () => {
99
+ let response = await request
100
+ .post(`${baseUrl}/authentication`)
101
+ .send({ accessToken: userIdAccessToken, strategy: 'jwt' })
102
+ let accessToken = response.body.accessToken
103
+ let user = response.body.user
104
+ expect(accessToken).toExist()
105
+ expect(accessToken).not.to.equal(userIdAccessToken)
106
+ expect(user).toExist()
107
+ response = await request
108
+ .post(`${baseUrl}/authentication`)
109
+ .send({ accessToken: emailAccessToken, strategy: 'jwt' })
110
+ accessToken = response.body.accessToken
111
+ user = response.body.user
112
+ expect(accessToken).toExist()
113
+ expect(accessToken).not.to.equal(emailAccessToken)
114
+ expect(user).toExist()
115
+ response = await request
116
+ .post(`${baseUrl}/authentication`)
117
+ .send({ accessToken: phoneAccessToken, strategy: 'jwt' })
118
+ accessToken = response.body.accessToken
119
+ user = response.body.user
120
+ expect(accessToken).toExist()
121
+ expect(accessToken).not.to.equal(phoneAccessToken)
122
+ expect(user).toExist()
123
+ response = await request
124
+ .post(`${baseUrl}/authentication`)
125
+ .send({ accessToken: statelessAccessToken, strategy: 'jwt' })
126
+ accessToken = response.body.accessToken
127
+ user = response.body.user
128
+ expect(accessToken).toExist()
129
+ expect(accessToken).not.to.equal(statelessAccessToken)
130
+ expect(user).beUndefined()
131
+ })
132
+
133
+ it('checks for user information disclosure', async () => {
134
+ // Should not retrieve internal user secret information like password in any case
135
+ // Should not list others users in case of requests with identified user
136
+ let response = await request
137
+ .get(`${baseUrl}/users`)
138
+ .set('Authorization', 'Bearer ' + userIdAccessToken)
139
+ let users = response.body.data
140
+ expect(users.length).to.equal(1)
141
+ let user = users[0]
142
+ expect(user._id).to.equal(userObject._id.toString())
143
+ expect(user.password).beUndefined()
144
+ expect(user.previousPasswords).beUndefined()
145
+ expect(user.permissions).toExist()
146
+ response = await request
147
+ .get(`${baseUrl}/users`)
148
+ .set('Authorization', 'Bearer ' + emailAccessToken)
149
+ users = response.body.data
150
+ expect(users.length).to.equal(1)
151
+ user = users[0]
152
+ expect(user._id).to.equal(userObject._id.toString())
153
+ expect(user.password).beUndefined()
154
+ expect(user.previousPasswords).beUndefined()
155
+ expect(user.permissions).toExist()
156
+ response = await request
157
+ .get(`${baseUrl}/users`)
158
+ .set('Authorization', 'Bearer ' + phoneAccessToken)
159
+ users = response.body.data
160
+ expect(users.length).to.equal(1)
161
+ user = users[0]
162
+ expect(user._id).to.equal(userObject._id.toString())
163
+ expect(user.password).beUndefined()
164
+ expect(user.previousPasswords).beUndefined()
165
+ expect(user.permissions).toExist()
166
+ // Should not list users in case of request without identified user
167
+ try {
168
+ response = await request
169
+ .get(`${baseUrl}/users/${anotherUserObject._id}`)
170
+ .set('Authorization', 'Bearer ' + statelessAccessToken)
171
+ } catch (error) {
172
+ // Not sure why but in this case the raised error is in text/html format
173
+ expect(error.status).to.equal(500)
174
+ expect(error.response.text.includes('MethodNotAllowed')).beTrue()
175
+ }
176
+ /*
177
+ response = await request
178
+ .get(`${baseUrl}/users`)
179
+ .set('Authorization', 'Bearer ' + statelessAccessToken)
180
+ users = response.body.data
181
+ expect(users.length).to.equal(2)
182
+ user = users[0]
183
+ expect(user._id).to.equal(userObject._id.toString())
184
+ expect(user.password).beUndefined()
185
+ expect(user.previousPasswords).beUndefined()
186
+ expect(user.permissions).beUndefined()
187
+ user = users[1]
188
+ expect(user._id).to.equal(anotherUserObject._id.toString())
189
+ expect(user.password).beUndefined()
190
+ expect(user.previousPasswords).beUndefined()
191
+ expect(user.permissions).beUndefined()
192
+ */
193
+ // Should not get others users in case of requests with identified user
194
+ try {
195
+ response = await request
196
+ .get(`${baseUrl}/users/${anotherUserObject._id}`)
197
+ .set('Authorization', 'Bearer ' + userIdAccessToken)
198
+ } catch (error) {
199
+ // Not sure why but in this case the raised error is in text/html format
200
+ expect(error.status).to.equal(500)
201
+ expect(error.response.text.includes('MethodNotAllowed')).beTrue()
202
+ }
203
+ try {
204
+ response = await request
205
+ .get(`${baseUrl}/users/${anotherUserObject._id}`)
206
+ .set('Authorization', 'Bearer ' + emailAccessToken)
207
+ } catch (error) {
208
+ // Not sure why but in this case the raised error is in text/html format
209
+ expect(error.status).to.equal(500)
210
+ expect(error.response.text.includes('MethodNotAllowed')).beTrue()
211
+ }
212
+ try {
213
+ response = await request
214
+ .get(`${baseUrl}/users/${anotherUserObject._id}`)
215
+ .set('Authorization', 'Bearer ' + phoneAccessToken)
216
+ } catch (error) {
217
+ // Not sure why but in this case the raised error is in text/html format
218
+ expect(error.status).to.equal(500)
219
+ expect(error.response.text.includes('MethodNotAllowed')).beTrue()
220
+ }
221
+ try {
222
+ response = await request
223
+ .get(`${baseUrl}/users/${anotherUserObject._id}`)
224
+ .set('Authorization', 'Bearer ' + statelessAccessToken)
225
+ } catch (error) {
226
+ // Not sure why but in this case the raised error is in text/html format
227
+ expect(error.status).to.equal(500)
228
+ expect(error.response.text.includes('MethodNotAllowed')).beTrue()
229
+ }
230
+ })
231
+
232
+ it('checks for user information integrity', async () => {
233
+ // Should not be able to update information of others users if not administrator
234
+ try {
235
+ await request
236
+ .patch(`${baseUrl}/users/${anotherUserObject._id}`)
237
+ .set('Authorization', 'Bearer ' + userIdAccessToken)
238
+ .send({ name: 'new name' })
239
+ } catch (error) {
240
+ // Not sure why but in this case the raised error is in text/html format
241
+ expect(error.status).to.equal(500)
242
+ expect(error.response.text.includes('NotFound')).beTrue()
243
+ }
244
+ try {
245
+ await request
246
+ .patch(`${baseUrl}/users/${anotherUserObject._id}`)
247
+ .set('Authorization', 'Bearer ' + emailAccessToken)
248
+ .send({ name: 'new name' })
249
+ } catch (error) {
250
+ // Not sure why but in this case the raised error is in text/html format
251
+ expect(error.status).to.equal(500)
252
+ expect(error.response.text.includes('NotFound')).beTrue()
253
+ }
254
+ try {
255
+ await request
256
+ .patch(`${baseUrl}/users/${anotherUserObject._id}`)
257
+ .set('Authorization', 'Bearer ' + phoneAccessToken)
258
+ .send({ name: 'new name' })
259
+ } catch (error) {
260
+ // Not sure why but in this case the raised error is in text/html format
261
+ expect(error.status).to.equal(500)
262
+ expect(error.response.text.includes('NotFound')).beTrue()
263
+ }
264
+ try {
265
+ await request
266
+ .patch(`${baseUrl}/users/${anotherUserObject._id}`)
267
+ .set('Authorization', 'Bearer ' + statelessAccessToken)
268
+ .send({ name: 'new name' })
269
+ } catch (error) {
270
+ // Not sure why but in this case the raised error is in text/html format
271
+ expect(error.status).to.equal(500)
272
+ expect(error.response.text.includes('Forbidden')).beTrue()
273
+ }
274
+ // Should be possible otherwise
275
+ const response = await request
276
+ .patch(`${baseUrl}/users/${userObject._id}`)
277
+ .set('Authorization', 'Bearer ' + adminAccessToken)
278
+ .send({ name: 'new name' })
279
+ const user = response.body
280
+ expect(user.name).to.equal('new name')
281
+ })
282
+
283
+ it('checks for user privilege escalation', async () => {
284
+ // Should not be able to upgrade user permissions when not administrator
285
+ try {
286
+ await request
287
+ .patch(`${baseUrl}/users/${userObject._id}`)
288
+ .set('Authorization', 'Bearer ' + userIdAccessToken)
289
+ .send({ permissions: 'administrator' })
290
+ } catch (error) {
291
+ // Not sure why but in this case the raised error is in text/html format
292
+ expect(error.status).to.equal(500)
293
+ expect(error.response.text.includes('BadRequest')).beTrue()
294
+ }
295
+ try {
296
+ await request
297
+ .patch(`${baseUrl}/users/${userObject._id}`)
298
+ .set('Authorization', 'Bearer ' + emailAccessToken)
299
+ .send({ permissions: 'administrator' })
300
+ } catch (error) {
301
+ // Not sure why but in this case the raised error is in text/html format
302
+ expect(error.status).to.equal(500)
303
+ expect(error.response.text.includes('BadRequest')).beTrue()
304
+ }
305
+ try {
306
+ await request
307
+ .patch(`${baseUrl}/users/${userObject._id}`)
308
+ .set('Authorization', 'Bearer ' + phoneAccessToken)
309
+ .send({ permissions: 'administrator' })
310
+ } catch (error) {
311
+ // Not sure why but in this case the raised error is in text/html format
312
+ expect(error.status).to.equal(500)
313
+ expect(error.response.text.includes('BadRequest')).beTrue()
314
+ }
315
+ try {
316
+ await request
317
+ .patch(`${baseUrl}/users/${userObject._id}`)
318
+ .set('Authorization', 'Bearer ' + statelessAccessToken)
319
+ .send({ permissions: 'administrator' })
320
+ } catch (error) {
321
+ // Not sure why but in this case the raised error is in text/html format
322
+ expect(error.status).to.equal(500)
323
+ expect(error.response.text.includes('Forbidden')).beTrue()
324
+ }
325
+ // Should be possible otherwise
326
+ const response = await request
327
+ .patch(`${baseUrl}/users/${userObject._id}`)
328
+ .set('Authorization', 'Bearer ' + adminAccessToken)
329
+ .send({ permissions: 'manager' })
330
+ const user = response.body
331
+ expect(user.permissions).to.equal('manager')
332
+ })
333
+
334
+ it('checks users removal', async () => {
335
+ // Should not be able to remove others users if not administrator
336
+ try {
337
+ await request
338
+ .delete(`${baseUrl}/users/${anotherUserObject._id}`)
339
+ .set('Authorization', 'Bearer ' + userIdAccessToken)
340
+ } catch (error) {
341
+ // Not sure why but in this case the raised error is in text/html format
342
+ expect(error.status).to.equal(500)
343
+ expect(error.response.text.includes('NotFound')).beTrue()
344
+ }
345
+ try {
346
+ await request
347
+ .delete(`${baseUrl}/users/${anotherUserObject._id}`)
348
+ .set('Authorization', 'Bearer ' + emailAccessToken)
349
+ } catch (error) {
350
+ // Not sure why but in this case the raised error is in text/html format
351
+ expect(error.status).to.equal(500)
352
+ expect(error.response.text.includes('NotFound')).beTrue()
353
+ }
354
+ try {
355
+ await request
356
+ .delete(`${baseUrl}/users/${anotherUserObject._id}`)
357
+ .set('Authorization', 'Bearer ' + phoneAccessToken)
358
+ } catch (error) {
359
+ // Not sure why but in this case the raised error is in text/html format
360
+ expect(error.status).to.equal(500)
361
+ expect(error.response.text.includes('NotFound')).beTrue()
362
+ }
363
+ try {
364
+ await request
365
+ .delete(`${baseUrl}/users/${anotherUserObject._id}`)
366
+ .set('Authorization', 'Bearer ' + statelessAccessToken)
367
+ } catch (error) {
368
+ // Not sure why but in this case the raised error is in text/html format
369
+ expect(error.status).to.equal(500)
370
+ expect(error.response.text.includes('Forbidden')).beTrue()
371
+ }
372
+ await userService.remove(userObject._id)
373
+ await userService.remove(anotherUserObject._id)
374
+ })
375
+ // Let enough time to process
376
+ .timeout(5000)
377
+
378
+ // Cleanup
379
+ after(async () => {
380
+ if (server) await server.close()
381
+ await app.db.instance.dropDatabase()
382
+ await app.db.disconnect()
383
+ })
384
+ })
@@ -276,7 +276,7 @@ describe('map:grid-source', () => {
276
276
 
277
277
  it('is possible to create a Weacast source from makeGridSource', () => {
278
278
  const [key, conf] = extractGridSourceConfig(weacastOptions)
279
- source = makeGridSource(key, { weacastApi: weacastOptions.weacastApi })
279
+ source = makeGridSource(key, { planetApi: weacastOptions.weacastApi })
280
280
  expect(source).to.exist
281
281
  expect(conf).to.deep.equal(weacastOptions.weacast)
282
282
  sourceConfig = conf
@@ -0,0 +1,56 @@
1
+ {"level":"info","message":"Logger configured"}
2
+ {"level":"info","message":"Initializing weacast-gfs plugin"}
3
+ {"level":"info","message":"Initializing gfs-world forecast"}
4
+ {"level":"info","message":"Checking for up-to-date forecast data on gfs-world/u-wind"}
5
+ {"level":"info","message":"Checking for up-to-date forecast data on gfs-world/v-wind"}
6
+ {"level":"error","message":"Could not update gfs-world/v-wind forecast at 2026-03-10T06:00:00Z for run 2026-03-10T00:00:00Z"}
7
+ {"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/v-wind/2026-03-10_00-00-00_2026-03-10_06-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
8
+ {"level":"error","message":"Could not update gfs-world/u-wind forecast at 2026-03-10T06:00:00Z for run 2026-03-10T00:00:00Z"}
9
+ {"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/u-wind/2026-03-10_00-00-00_2026-03-10_06-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
10
+ {"level":"error","message":"Could not update gfs-world/v-wind forecast at 2026-03-10T06:00:00Z for run 2026-03-09T18:00:00Z"}
11
+ {"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/v-wind/2026-03-09_18-00-00_2026-03-10_06-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
12
+ {"level":"error","message":"Could not update gfs-world/u-wind forecast at 2026-03-10T06:00:00Z for run 2026-03-09T18:00:00Z"}
13
+ {"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/u-wind/2026-03-09_18-00-00_2026-03-10_06-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
14
+ {"level":"error","message":"Could not update gfs-world/v-wind forecast at 2026-03-10T06:00:00Z for run 2026-03-09T12:00:00Z"}
15
+ {"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/v-wind/2026-03-09_12-00-00_2026-03-10_06-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
16
+ {"level":"error","message":"Could not update gfs-world/u-wind forecast at 2026-03-10T06:00:00Z for run 2026-03-09T12:00:00Z"}
17
+ {"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/u-wind/2026-03-09_12-00-00_2026-03-10_06-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
18
+ {"level":"error","message":"Could not update gfs-world/v-wind forecast at 2026-03-10T09:00:00Z for run 2026-03-10T00:00:00Z"}
19
+ {"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/v-wind/2026-03-10_00-00-00_2026-03-10_09-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
20
+ {"level":"error","message":"Could not update gfs-world/u-wind forecast at 2026-03-10T09:00:00Z for run 2026-03-10T00:00:00Z"}
21
+ {"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/u-wind/2026-03-10_00-00-00_2026-03-10_09-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
22
+ {"level":"error","message":"Could not update gfs-world/v-wind forecast at 2026-03-10T09:00:00Z for run 2026-03-09T18:00:00Z"}
23
+ {"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/v-wind/2026-03-09_18-00-00_2026-03-10_09-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
24
+ {"level":"error","message":"Could not update gfs-world/v-wind forecast at 2026-03-10T09:00:00Z for run 2026-03-09T12:00:00Z"}
25
+ {"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/v-wind/2026-03-09_12-00-00_2026-03-10_09-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
26
+ {"level":"info","message":"Completed forecast data update on gfs-world/v-wind"}
27
+ {"level":"error","message":"Could not update gfs-world/u-wind forecast at 2026-03-10T09:00:00Z for run 2026-03-09T18:00:00Z"}
28
+ {"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/u-wind/2026-03-09_18-00-00_2026-03-10_09-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
29
+ {"level":"error","message":"Could not update gfs-world/u-wind forecast at 2026-03-10T09:00:00Z for run 2026-03-09T12:00:00Z"}
30
+ {"level":"error","message":"Command failed: /home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json --data /home/robin/Taff/kalisio/kdk/test/api/map/forecast-data/gfs-world/u-wind/2026-03-09_12-00-00_2026-03-10_09-00-00.grib\n/home/robin/Taff/kalisio/kdk/node_modules/@weacast/grib2json/bin/grib2json: 3: /bin/java: not found\n"}
31
+ {"level":"info","message":"Completed forecast data update on gfs-world/u-wind"}
32
+ {"level":"error","message":"Cannot check alert 69afde354d314fa3bd9e24a8 as no data is available for gfs-world"}
33
+ {"level":"error","message":"Cannot check alert 69afde354d314fa3bd9e24a8 as no data is available for gfs-world"}
34
+ {"level":"error","message":"Cannot check alert 69afde354d314fa3bd9e24a8 as no data is available for gfs-world"}
35
+ {"level":"error","message":"Cannot check alert 69afde444d314fa3bd9e24a9 as no data is available for gfs-world"}
36
+ {"level":"error","message":"Cannot check alert 69afde444d314fa3bd9e24a9 as no data is available for gfs-world"}
37
+ {"level":"error","message":"Cannot check alert 69afde444d314fa3bd9e24a9 as no data is available for gfs-world"}
38
+ {"level":"error","message":"Cannot check alert 69afde534d314fa3bd9e24aa as no data is available for gfs-world"}
39
+ {"level":"error","message":"Cannot check alert 69afde724d314fa3bd9e29ed as no data is available for features service vigicrues-observations"}
40
+ {"level":"error","message":"error: api/catalog - Method: create: Object with name equals to dummy already exist for service catalog"}
41
+ {"level":"info","message":"Logger configured"}
42
+ {"level":"error","message":"error: api/vigicrues-observations - Method: find: You are not allowed to use $accumulator operator"}
43
+ {"level":"error","message":"error: api/vigicrues-observations - Method: find: You are not allowed to use $function operator"}
44
+ {"level":"info","message":"Logger configured"}
45
+ {"level":"info","message":"Initializing weacast-gfs plugin"}
46
+ {"level":"info","message":"Initializing gfs-world forecast"}
47
+ {"level":"info","message":"Checking for up-to-date forecast data on gfs-world/u-wind"}
48
+ {"level":"info","message":"Checking for up-to-date forecast data on gfs-world/v-wind"}
49
+ {"level":"info","message":"Completed forecast data update on gfs-world/v-wind"}
50
+ {"level":"info","message":"Completed forecast data update on gfs-world/u-wind"}
51
+ {"level":"error","message":"Cannot check alert 69afe195ae25fbb35c793f22 as no data is available for gfs-world"}
52
+ {"level":"error","message":"Cannot check alert 69afe1b3ae25fbb35c794465 as no data is available for features service vigicrues-observations"}
53
+ {"level":"error","message":"error: api/catalog - Method: create: Object with name equals to dummy already exist for service catalog"}
54
+ {"level":"info","message":"Logger configured"}
55
+ {"level":"error","message":"error: api/vigicrues-observations - Method: find: You are not allowed to use $accumulator operator"}
56
+ {"level":"error","message":"error: api/vigicrues-observations - Method: find: You are not allowed to use $function operator"}
package/vite/package.json CHANGED
@@ -37,6 +37,7 @@
37
37
  "node": ">= 16.0.0"
38
38
  },
39
39
  "scripts": {
40
+ "fix-protomaps-leaflet": "fix-esm-import-path node_modules/protomaps-leaflet/dist/index.js",
40
41
  "build:app": "cross-env BUILD_MODE=app vite build",
41
42
  "build:app:globe": "cross-env BUILD_MODE=app GLOBE=1 vite build",
42
43
  "extras:css": "shx mkdir -p ../client/css && shx cp -R ../extras/css/* ../client/css",
@@ -47,7 +48,9 @@
47
48
  "build:lib:globe:debug": "cross-env BUILD_MODE=lib GLOBE=1 DEBUG=1 vite build",
48
49
  "build:lib": "cross-env BUILD_MODE=lib vite build",
49
50
  "build:lib:globe": "cross-env BUILD_MODE=lib GLOBE=1 vite build",
50
- "build:libs": "npm run build:lib:extras && npm run build:lib:debug && npm run build:lib:globe:debug && npm run build:lib && npm run build:lib:globe",
51
+ "build:libs": "npm run build:lib:extras && npm run build:lib:debug && npm run build:lib:globe:debug && npm run fix-protomaps-leaflet && npm run build:lib && npm run build:lib:globe",
52
+ "test:core": "vitest --run --dir test/core",
53
+ "test": "npm-run-all --serial test:**",
51
54
  "dev": "vite dev",
52
55
  "dev:globe": "cross-env GLOBE=1 vite dev"
53
56
  },
@@ -84,8 +87,9 @@
84
87
  "@thumbmarkjs/thumbmarkjs": "^0.16.1",
85
88
  "@tmcw/togeojson": "^4.5.0",
86
89
  "@turf/turf": "^6.5.0",
87
- "@weacast/core": "^2.2.1",
88
90
  "@vitejs/plugin-vue": "^6.0.0",
91
+ "@vue/test-utils": "^2.4.6",
92
+ "@weacast/core": "^2.2.1",
89
93
  "abort-controller": "^3.0.0",
90
94
  "ajv": "^8.12.0",
91
95
  "ajv-formats": "^2.1.1",
@@ -107,6 +111,7 @@
107
111
  "debug": "^4.1.0",
108
112
  "email-validator": "^2.0.4",
109
113
  "feathers-reactive": "^0.11.0",
114
+ "fix-esm-import-path": "^1.10.0",
110
115
  "formatcoords": "^1.1.3",
111
116
  "fs-extra": "^8.1.0",
112
117
  "geotiff": "^2.1.3",
@@ -115,11 +120,13 @@
115
120
  "iso8601-js-period": "^0.2.1",
116
121
  "jquery": "^3.2.1",
117
122
  "js-yaml": "^3.13.1",
123
+ "jsdom": "^27.3.0",
118
124
  "jsts": "^2.12.1",
119
125
  "jwt-decode": "^3.1.2",
120
126
  "leaflet": "1.6.0",
121
127
  "leaflet-arrowheads": "^1.4.0",
122
128
  "leaflet-fullscreen": "^1.0.2",
129
+ "leaflet-gesture-handling": "^1.2.2",
123
130
  "leaflet-heatmap": "^1.0.0",
124
131
  "leaflet-pixi-overlay": "1.9.3",
125
132
  "leaflet-realtime": "^2.2.0",
@@ -140,6 +147,7 @@
140
147
  "moment": "^2.29.3",
141
148
  "moment-timezone": "^0.5.35",
142
149
  "node-fetch": "^2.6.7",
150
+ "npm-run-all": "^4.1.1",
143
151
  "papaparse": "^5.3.2",
144
152
  "path-browserify": "^1.0.1",
145
153
  "pinch-zoom-element": "^1.1.1",
@@ -162,6 +170,7 @@
162
170
  "vite": "^7.0.6",
163
171
  "vite-plugin-node-polyfills": "^0.24.0",
164
172
  "vite-plugin-static-copy": "^3.1.1",
173
+ "vitest": "^4.0.15",
165
174
  "vue": "3.2.45",
166
175
  "vue-i18n": "^9.2.0-beta.35",
167
176
  "vue-router": "4.1.3",
@@ -0,0 +1,77 @@
1
+ import { ref } from 'vue'
2
+ import { feathers } from '@feathersjs/feathers'
3
+ import { rx } from 'feathers-reactive'
4
+ import { memory } from '@feathersjs/memory'
5
+ import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest'
6
+ import { flushPromises } from '@vue/test-utils'
7
+ import { kdkCore, kdkMap } from '../../../client/kdk.client.map.js'
8
+
9
+ describe('core:composables', () => {
10
+ let client
11
+ const nbItemsPerPage = ref(2)
12
+ const baseQuery = ref({ $sort: { _id: 1 } })
13
+ const filterQuery = ref({})
14
+ const getService = ref(() => client.service('/messages'))
15
+
16
+ beforeAll(() => {
17
+ client = feathers()
18
+ .configure(rx({ idField: '_id' }))
19
+ const service = memory({
20
+ id: '_id',
21
+ store: {
22
+ 0: { _id: 1, name: 'xxx' },
23
+ 1: { _id: 2, name: 'yyy' },
24
+ 2: { _id: 3, name: 'zzz' }
25
+ },
26
+ paginate: { default: 5, max: 5 }
27
+ })
28
+ client.use('/messages', service).hooks({
29
+ before: {
30
+ // Required as some options like $locale are only supported by server-side services
31
+ all: [kdkCore.hooks.removeServerSideParameters]
32
+ }
33
+ })
34
+ })
35
+
36
+ it('refresh collection in paginated mode', async () => {
37
+ const { items, currentPage, refreshCollection } = kdkCore.composables.useCollection({
38
+ nbItemsPerPage, baseQuery, filterQuery, getService
39
+ })
40
+ refreshCollection()
41
+ await vi.waitFor(() => {
42
+ expect(items.value).to.deep.equal([{ _id: 1, name: 'xxx' }, { _id: 2, name: 'yyy' }])
43
+ })
44
+ currentPage.value++
45
+ refreshCollection()
46
+ await vi.waitFor(() => {
47
+ expect(items.value).to.deep.equal([{ _id: 3, name: 'zzz' }])
48
+ })
49
+ filterQuery.value = { name: 'yyy' }
50
+ await vi.waitFor(() => {
51
+ expect(items.value).to.deep.equal([{ _id: 2, name: 'yyy' }])
52
+ })
53
+ })
54
+
55
+ it('refresh collection in append mode', async () => {
56
+ // Reset any filter
57
+ filterQuery.value = {}
58
+ const { items, currentPage, refreshCollection } = kdkCore.composables.useCollection({
59
+ nbItemsPerPage, baseQuery, filterQuery, getService, appendItems: ref(true)
60
+ })
61
+ refreshCollection()
62
+ await vi.waitFor(() => {
63
+ expect(items.value).to.deep.equal([{ _id: 1, name: 'xxx' }, { _id: 2, name: 'yyy' }])
64
+ })
65
+ currentPage.value++
66
+ refreshCollection()
67
+ await vi.waitFor(() => {
68
+ expect(items.value).to.deep.equal([{ _id: 1, name: 'xxx' }, { _id: 2, name: 'yyy' }, { _id: 3, name: 'zzz' }])
69
+ })
70
+ filterQuery.value = { name: 'yyy' }
71
+ await vi.waitFor(() => {
72
+ expect(items.value).to.deep.equal([{ _id: 2, name: 'yyy' }])
73
+ })
74
+ })
75
+
76
+ afterAll(() => {})
77
+ })
@@ -0,0 +1,13 @@
1
+ import { defineConfig, mergeConfig } from 'vite'
2
+ import viteConfig from './vite.config'
3
+ import 'vitest/config'
4
+
5
+ export default mergeConfig(
6
+ viteConfig,
7
+ defineConfig({
8
+ test: {
9
+ environment: 'jsdom',
10
+ disableConsoleIntercept: true
11
+ }
12
+ })
13
+ )