@geode/opengeodeweb-front 10.34.0-rc.2 → 10.34.0-rc.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (499) hide show
  1. package/.build/opengeodeweb_front_schemas.js +175 -0
  2. package/.build/server/utils/app_config.js +57 -0
  3. package/.build/server/utils/cleanup.js +135 -0
  4. package/.build/server/utils/cloud.js +156 -0
  5. package/.build/server/utils/microservices.js +153 -0
  6. package/.build/server/utils/path.js +108 -0
  7. package/.build/server/utils/scripts.js +134 -0
  8. package/.build/server/utils/server.js +44 -0
  9. package/.build/server/utils/server_config.js +51 -0
  10. package/.build/server/utils/stream.js +6 -0
  11. package/.build/server/utils/ws_client.js +100 -0
  12. package/.build/shared/app_mode.js +8 -0
  13. package/.build/shared/scripts.js +49 -0
  14. package/.build/shared/utils/call_raw.js +31 -0
  15. package/.build/shared/utils/call_schema.js +28 -0
  16. package/.build/shared/utils/fetch_raw.js +52 -0
  17. package/.build/shared/utils/fetch_schema.js +32 -0
  18. package/.build/shared/utils/file.js +14 -0
  19. package/.build/shared/utils/parse_boolean.js +23 -0
  20. package/.build/shared/utils/response_handlers/load.js +50 -0
  21. package/.build/shared/utils/types.js +1 -0
  22. package/.build/shared/utils/validate_schema.js +17 -0
  23. package/README.md +8 -0
  24. package/app/assets/{geode_objects.js → geode_objects.ts} +8 -1
  25. package/app/components/ActionButton.vue +28 -12
  26. package/app/components/Basic/Slider.vue +2 -2
  27. package/app/components/Basic/Switch.vue +2 -2
  28. package/app/components/CameraManager/List.vue +11 -11
  29. package/app/components/CameraManager/Saver.vue +8 -4
  30. package/app/components/CameraManager.vue +24 -12
  31. package/app/components/CameraOrientation.vue +31 -17
  32. package/app/components/ClippingPlaneCard.vue +13 -12
  33. package/app/components/ClippingPlanes.vue +31 -21
  34. package/app/components/CrsSelector.vue +26 -18
  35. package/app/components/DeleteDialog.vue +18 -16
  36. package/app/components/DragAndDrop.vue +55 -37
  37. package/app/components/DragAndDropInternal/DragAndDropInline.vue +31 -16
  38. package/app/components/DragAndDropInternal/DragAndDropOverlay.vue +32 -19
  39. package/app/components/ExtensionSelector.vue +34 -18
  40. package/app/components/FeedBack/ErrorBanner.vue +4 -3
  41. package/app/components/FeedBack/Snackers.vue +6 -5
  42. package/app/components/FetchingData.vue +8 -12
  43. package/app/components/FileSelector.vue +27 -17
  44. package/app/components/FileUploader.vue +51 -30
  45. package/app/components/GlassCard.vue +17 -13
  46. package/app/components/HybridRenderingView.vue +25 -12
  47. package/app/components/HybridViewerTooltip.vue +28 -26
  48. package/app/components/InfraConnected.vue +1 -1
  49. package/app/components/Launcher.vue +12 -10
  50. package/app/components/Loading/EcoMessages.vue +24 -13
  51. package/app/components/Loading/Header.vue +6 -7
  52. package/app/components/Loading/Progress.vue +6 -7
  53. package/app/components/Loading.vue +10 -14
  54. package/app/components/MissingFilesSelector.vue +35 -19
  55. package/app/components/ObjectSelector.vue +37 -21
  56. package/app/components/PackagesVersions.vue +16 -8
  57. package/app/components/Recaptcha.vue +17 -23
  58. package/app/components/RemoteRenderingView.vue +21 -15
  59. package/app/components/Ruler.vue +11 -9
  60. package/app/components/Screenshot.vue +25 -19
  61. package/app/components/SearchBar.vue +12 -6
  62. package/app/components/ShrinkFilter.vue +19 -14
  63. package/app/components/Step.vue +32 -12
  64. package/app/components/Stepper.vue +19 -7
  65. package/app/components/ToolPanel.vue +29 -13
  66. package/app/components/ViewToolbar.vue +53 -44
  67. package/app/components/Viewer/ContextMenu/CenterButton.vue +16 -9
  68. package/app/components/Viewer/ContextMenu/CircularItems.vue +13 -10
  69. package/app/components/Viewer/ContextMenu/ContextMenu.vue +40 -32
  70. package/app/components/Viewer/ContextMenu/ContextMenuItem.vue +31 -17
  71. package/app/components/Viewer/ContextMenu/InfoCard.vue +38 -22
  72. package/app/components/Viewer/EdgedCurve/PointsOptions.vue +8 -5
  73. package/app/components/Viewer/EdgedCurve/SpecificEdgesOptions.vue +67 -48
  74. package/app/components/Viewer/Generic/Mesh/CellsOptions.vue +74 -50
  75. package/app/components/Viewer/Generic/Mesh/EdgesOptions.vue +69 -50
  76. package/app/components/Viewer/Generic/Mesh/PointsOptions.vue +47 -35
  77. package/app/components/Viewer/Generic/Mesh/PolygonsOptions.vue +91 -51
  78. package/app/components/Viewer/Generic/Mesh/PolyhedraOptions.vue +74 -49
  79. package/app/components/Viewer/Generic/Model/BlocksOptions.vue +115 -53
  80. package/app/components/Viewer/Generic/Model/CornersOptions.vue +75 -37
  81. package/app/components/Viewer/Generic/Model/EdgesOptions.vue +13 -9
  82. package/app/components/Viewer/Generic/Model/LinesOptions.vue +110 -61
  83. package/app/components/Viewer/Generic/Model/ModelStyleCard.vue +32 -21
  84. package/app/components/Viewer/Generic/Model/ModelStyleOptions.vue +9 -5
  85. package/app/components/Viewer/Generic/Model/PointsOptions.vue +19 -13
  86. package/app/components/Viewer/Generic/Model/SurfacesOptions.vue +119 -49
  87. package/app/components/Viewer/Grid/2D/CellsOptions.vue +8 -5
  88. package/app/components/Viewer/Grid/2D/EdgesOptions.vue +8 -5
  89. package/app/components/Viewer/Grid/2D/PointsOptions.vue +8 -5
  90. package/app/components/Viewer/Grid/3D/CellsOptions.vue +8 -5
  91. package/app/components/Viewer/Grid/3D/EdgesOptions.vue +8 -5
  92. package/app/components/Viewer/Grid/3D/FacetsOptions.vue +8 -5
  93. package/app/components/Viewer/Grid/3D/PointsOptions.vue +8 -5
  94. package/app/components/Viewer/ObjectTree/Base/CommonTreeView.vue +120 -76
  95. package/app/components/Viewer/ObjectTree/Base/Controls.vue +25 -10
  96. package/app/components/Viewer/ObjectTree/Base/ItemLabel.vue +42 -17
  97. package/app/components/Viewer/ObjectTree/Base/StickyHeader.vue +22 -9
  98. package/app/components/Viewer/ObjectTree/Base/TreeRow.vue +29 -14
  99. package/app/components/Viewer/ObjectTree/Box.vue +32 -15
  100. package/app/components/Viewer/ObjectTree/Layout.vue +55 -35
  101. package/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue +63 -34
  102. package/app/components/Viewer/ObjectTree/Views/{ModelCollections.vue → ModelTree.vue} +101 -39
  103. package/app/components/Viewer/Options/AttributeColorBar.vue +14 -6
  104. package/app/components/Viewer/Options/AttributeRangeSelector.vue +8 -4
  105. package/app/components/Viewer/Options/AttributeSelector.vue +64 -33
  106. package/app/components/Viewer/Options/ColorMapList.vue +52 -24
  107. package/app/components/Viewer/Options/ColorMapPicker.vue +15 -11
  108. package/app/components/Viewer/Options/ColorPicker.vue +239 -50
  109. package/app/components/Viewer/Options/ColoringTypeSelector.vue +87 -67
  110. package/app/components/Viewer/Options/ColormapQuickPicker.vue +16 -12
  111. package/app/components/Viewer/Options/OptionsSection.vue +7 -5
  112. package/app/components/Viewer/Options/Sliders/Size.vue +3 -3
  113. package/app/components/Viewer/Options/Sliders/Slider.vue +9 -6
  114. package/app/components/Viewer/Options/Sliders/Width.vue +3 -3
  115. package/app/components/Viewer/Options/TextureItem.vue +29 -22
  116. package/app/components/Viewer/Options/TexturesSelector.vue +23 -12
  117. package/app/components/Viewer/Options/VisibilitySwitch.vue +3 -3
  118. package/app/components/Viewer/OverlappingObjectsPicker.vue +27 -12
  119. package/app/components/Viewer/PointSet/SpecificPointsOptions.vue +38 -26
  120. package/app/components/Viewer/Solid/EdgesOptions.vue +8 -5
  121. package/app/components/Viewer/Solid/PointsOptions.vue +8 -5
  122. package/app/components/Viewer/Solid/PolygonsOptions.vue +8 -5
  123. package/app/components/Viewer/Solid/SpecificPolyhedraOptions.vue +73 -48
  124. package/app/components/Viewer/Surface/EdgesOptions.vue +8 -5
  125. package/app/components/Viewer/Surface/PointsOptions.vue +8 -5
  126. package/app/components/Viewer/Surface/PolygonsOptions.vue +79 -49
  127. package/app/components/Viewer/Surface/Triangulated/TrianglesOptions.vue +8 -5
  128. package/app/components/Viewer/TetrahedralSolid/TetrahedraOptions.vue +8 -5
  129. package/app/components/Viewer/TetrahedralSolid/TrianglesOptions.vue +8 -5
  130. package/app/components/Viewer/Ui.vue +19 -14
  131. package/app/components/Wrapper.vue +16 -10
  132. package/app/components/ZScaling.vue +18 -10
  133. package/app/components/csv-preview/CsvPreviewer.vue +72 -50
  134. package/app/components/csv-preview/CsvSettings.vue +30 -50
  135. package/app/components/csv-preview/CsvTable.vue +34 -14
  136. package/app/composables/{batch_style.js → batch_style.ts} +9 -7
  137. package/app/composables/clipping_planes_widget.ts +204 -0
  138. package/app/composables/clipping_planes_widget_entries.ts +189 -0
  139. package/app/composables/copy_to_clipboard.ts +7 -0
  140. package/app/composables/global_attribute_style.ts +303 -0
  141. package/app/composables/hover_highlight.ts +127 -0
  142. package/app/composables/{model_collections.js → model_collections.ts} +28 -9
  143. package/app/composables/{model_components.js → model_components.ts} +28 -9
  144. package/app/composables/{project_manager.js → project_manager.ts} +77 -20
  145. package/app/composables/responsive_middle_truncate.ts +48 -0
  146. package/app/composables/{run_function_when_microservices_connected.js → run_function_when_microservices_connected.ts} +1 -1
  147. package/app/composables/stepper_tree.ts +79 -0
  148. package/app/composables/tree_filter.ts +194 -0
  149. package/app/composables/{tree_keyboard_nav.js → tree_keyboard_nav.ts} +62 -20
  150. package/app/composables/{tree_scroll.js → tree_scroll.ts} +61 -12
  151. package/app/composables/use_adaptive_styles.ts +186 -0
  152. package/app/composables/use_overlapping_picker.ts +263 -0
  153. package/app/composables/use_quick_colormap.ts +55 -0
  154. package/app/composables/virtual_tree.ts +271 -0
  155. package/app/composables/vtk_implicit_plane_widget.d.ts +2 -0
  156. package/app/plugins/{auto_store_register.js → auto_store_register.ts} +3 -5
  157. package/app/plugins/click_outside_ignore_snackbars.client.ts +36 -0
  158. package/app/stores/app.ts +252 -0
  159. package/app/stores/app_helpers/extension.ts +179 -0
  160. package/app/stores/{back.js → back.ts} +54 -28
  161. package/app/stores/camera_manager.ts +80 -0
  162. package/app/stores/{cloud.js → cloud.ts} +18 -13
  163. package/app/stores/data.ts +392 -0
  164. package/app/stores/data_helpers/collections.ts +138 -0
  165. package/app/stores/data_helpers/mesh.ts +169 -0
  166. package/app/stores/data_style.ts +167 -0
  167. package/app/stores/{feedback.js → feedback.ts} +19 -8
  168. package/app/stores/{hybrid_viewer.js → hybrid_viewer.ts} +49 -45
  169. package/app/stores/infra.ts +106 -0
  170. package/app/stores/{menu.js → menu.ts} +67 -36
  171. package/app/stores/treeview.ts +383 -0
  172. package/app/stores/{viewer.js → viewer.ts} +75 -42
  173. package/app/utils/attributes.ts +40 -0
  174. package/app/utils/clipping_planes.ts +222 -0
  175. package/app/utils/color_picker.js +54 -0
  176. package/app/utils/colormap.ts +102 -0
  177. package/app/utils/default_styles/{constants.js → constants.ts} +25 -12
  178. package/app/utils/default_styles/{index.js → index.ts} +4 -3
  179. package/app/utils/default_styles/meshes.ts +264 -0
  180. package/app/utils/default_styles/{models.js → models.ts} +106 -52
  181. package/app/utils/{extension.js → extension.ts} +63 -19
  182. package/app/utils/{import_workflow.js → import_workflow.ts} +39 -22
  183. package/app/utils/{log.js → log.ts} +12 -2
  184. package/app/utils/{name_cleaner.js → name_cleaner.ts} +6 -6
  185. package/app/utils/status.ts +19 -0
  186. package/app/utils/{stores.js → stores.ts} +5 -5
  187. package/app/utils/{string.js → string.ts} +6 -6
  188. package/app/utils/{treeview.js → treeview.ts} +4 -1
  189. package/internal/database/{base_database.js → base_database.ts} +7 -3
  190. package/internal/database/database.ts +102 -0
  191. package/internal/database/{extended_database.js → extended_database.ts} +5 -1
  192. package/internal/database/tables/camera_positions.ts +6 -0
  193. package/internal/database/tables/{data.js → data.ts} +3 -1
  194. package/internal/database/tables/data_style.ts +6 -0
  195. package/internal/database/tables/model_component_datastyle.ts +6 -0
  196. package/internal/database/tables/model_component_type_datastyle.ts +6 -0
  197. package/internal/database/tables/model_components.ts +6 -0
  198. package/internal/database/tables/model_components_relation.ts +6 -0
  199. package/internal/database/tables/table_definition.ts +5 -0
  200. package/internal/stores/data_style/mesh/cells/cell.ts +279 -0
  201. package/internal/stores/data_style/mesh/cells/{color.js → color.ts} +13 -7
  202. package/internal/stores/data_style/mesh/cells/common.ts +50 -0
  203. package/internal/stores/data_style/mesh/cells/index.ts +161 -0
  204. package/internal/stores/data_style/mesh/cells/{textures.js → textures.ts} +14 -8
  205. package/internal/stores/data_style/mesh/cells/vertex.ts +285 -0
  206. package/internal/stores/data_style/mesh/cells/visibility.ts +46 -0
  207. package/internal/stores/data_style/mesh/edges/{color.js → color.ts} +13 -7
  208. package/internal/stores/data_style/mesh/edges/common.ts +41 -0
  209. package/internal/stores/data_style/mesh/edges/edge.ts +279 -0
  210. package/internal/stores/data_style/mesh/edges/index.ts +155 -0
  211. package/internal/stores/data_style/mesh/edges/vertex.ts +285 -0
  212. package/internal/stores/data_style/mesh/edges/visibility.ts +45 -0
  213. package/internal/stores/data_style/mesh/edges/width.ts +42 -0
  214. package/internal/stores/data_style/mesh/{index.js → index.ts} +34 -14
  215. package/internal/stores/data_style/mesh/points/{color.js → color.ts} +13 -7
  216. package/internal/stores/data_style/mesh/points/common.ts +51 -0
  217. package/internal/stores/data_style/mesh/points/index.ts +133 -0
  218. package/internal/stores/data_style/mesh/points/size.ts +43 -0
  219. package/internal/stores/data_style/mesh/points/vertex.ts +285 -0
  220. package/internal/stores/data_style/mesh/points/visibility.ts +49 -0
  221. package/internal/stores/data_style/mesh/polygons/{color.js → color.ts} +13 -7
  222. package/internal/stores/data_style/mesh/polygons/common.ts +50 -0
  223. package/internal/stores/data_style/mesh/polygons/index.ts +167 -0
  224. package/internal/stores/data_style/mesh/polygons/polygon.ts +282 -0
  225. package/internal/stores/data_style/mesh/polygons/{textures.js → textures.ts} +14 -8
  226. package/internal/stores/data_style/mesh/polygons/vertex.ts +288 -0
  227. package/internal/stores/data_style/mesh/polygons/visibility.ts +48 -0
  228. package/internal/stores/data_style/mesh/polyhedra/{color.js → color.ts} +13 -7
  229. package/internal/stores/data_style/mesh/polyhedra/common.ts +41 -0
  230. package/internal/stores/data_style/mesh/polyhedra/index.ts +157 -0
  231. package/internal/stores/data_style/mesh/polyhedra/polyhedron.ts +294 -0
  232. package/internal/stores/data_style/mesh/polyhedra/vertex.ts +288 -0
  233. package/internal/stores/data_style/mesh/polyhedra/visibility.ts +48 -0
  234. package/internal/stores/data_style/model/blocks/{color.js → color.ts} +50 -13
  235. package/internal/stores/data_style/model/blocks/common.ts +67 -0
  236. package/internal/stores/data_style/model/blocks/{index.js → index.ts} +111 -66
  237. package/internal/stores/data_style/model/blocks/polyhedron.ts +363 -0
  238. package/internal/stores/data_style/model/blocks/vertex.ts +349 -0
  239. package/internal/stores/data_style/model/blocks/visibility.ts +37 -0
  240. package/internal/stores/data_style/model/color.ts +348 -0
  241. package/internal/stores/data_style/model/common.ts +262 -0
  242. package/internal/stores/data_style/model/corners/{color.js → color.ts} +49 -10
  243. package/internal/stores/data_style/model/corners/common.ts +71 -0
  244. package/internal/stores/data_style/model/corners/{index.js → index.ts} +86 -47
  245. package/internal/stores/data_style/model/corners/vertex.ts +315 -0
  246. package/internal/stores/data_style/model/corners/visibility.ts +39 -0
  247. package/internal/stores/data_style/model/edges/common.ts +29 -0
  248. package/internal/stores/data_style/model/edges/{index.js → index.ts} +2 -7
  249. package/internal/stores/data_style/model/edges/visibility.ts +55 -0
  250. package/internal/stores/data_style/model/{index.js → index.ts} +24 -11
  251. package/internal/stores/data_style/model/lines/{color.js → color.ts} +47 -10
  252. package/internal/stores/data_style/model/lines/common.ts +63 -0
  253. package/internal/stores/data_style/model/lines/edge.ts +343 -0
  254. package/internal/stores/data_style/model/lines/{index.js → index.ts} +108 -66
  255. package/internal/stores/data_style/model/lines/vertex.ts +344 -0
  256. package/internal/stores/data_style/model/lines/visibility.ts +37 -0
  257. package/internal/stores/data_style/model/points/common.ts +25 -0
  258. package/internal/stores/data_style/model/points/index.ts +35 -0
  259. package/internal/stores/data_style/model/points/size.ts +44 -0
  260. package/internal/stores/data_style/model/points/visibility.ts +46 -0
  261. package/internal/stores/data_style/model/selection.ts +138 -0
  262. package/internal/stores/data_style/model/surfaces/{color.js → color.ts} +47 -10
  263. package/internal/stores/data_style/model/surfaces/common.ts +69 -0
  264. package/internal/stores/data_style/model/surfaces/{index.js → index.ts} +113 -66
  265. package/internal/stores/data_style/model/surfaces/polygon.ts +347 -0
  266. package/internal/stores/data_style/model/surfaces/vertex.ts +351 -0
  267. package/internal/stores/data_style/model/surfaces/visibility.ts +37 -0
  268. package/internal/stores/data_style/model/{visibility.js → visibility.ts} +112 -32
  269. package/internal/stores/data_style/state.ts +281 -0
  270. package/internal/stores/data_style/types.ts +30 -0
  271. package/internal/stores/hybrid_viewer/brightness.ts +124 -0
  272. package/internal/stores/hybrid_viewer/camera.ts +326 -0
  273. package/internal/stores/hybrid_viewer/{camera_animation.js → camera_animation.ts} +30 -12
  274. package/internal/stores/hybrid_viewer/{constants.js → constants.ts} +2 -2
  275. package/internal/stores/hybrid_viewer/core.ts +64 -0
  276. package/internal/stores/hybrid_viewer/{filters.js → filters.ts} +10 -13
  277. package/internal/stores/hybrid_viewer/highlight.ts +183 -0
  278. package/internal/stores/hybrid_viewer/{ruler.js → ruler.ts} +50 -22
  279. package/internal/stores/hybrid_viewer/scene.ts +125 -0
  280. package/internal/stores/hybrid_viewer/viewport.ts +177 -0
  281. package/internal/stores/hybrid_viewer/vtk_types.ts +58 -0
  282. package/internal/utils/api_fetch.ts +133 -0
  283. package/internal/utils/upload_file.ts +115 -0
  284. package/internal/utils/viewer_call.ts +99 -0
  285. package/internal/utils/ws_client.ts +54 -0
  286. package/nuxt.config.ts +168 -0
  287. package/opengeodeweb_front_schemas.json +2 -2
  288. package/package.json +49 -13
  289. package/server/api/cloud/extensions/{run.post.js → run.post.ts} +16 -12
  290. package/server/api/local/app/project_folder_path.post.ts +33 -0
  291. package/server/api/local/app/run_back.post.ts +39 -0
  292. package/server/api/local/app/run_viewer.post.ts +39 -0
  293. package/server/api/local/extensions/{kill.post.js → kill.post.ts} +15 -8
  294. package/server/api/local/extensions/{run.post.js → run.post.ts} +17 -12
  295. package/server/api/local/extensions/upload.put.ts +71 -0
  296. package/server/api/microservice/app/{get_is_app_ready.get.js → get_is_app_ready.get.ts} +5 -5
  297. package/server/api/microservice/app/schemas/get_is_app_ready.json +1 -1
  298. package/server/api/microservice/app/set_app_base_url.post.ts +29 -0
  299. package/server/api/microservice/app/set_back_base_url.post.ts +26 -0
  300. package/server/api/microservice/app/set_is_app_ready.post.ts +29 -0
  301. package/server/api/microservice/app/set_viewer_base_url.post.ts +26 -0
  302. package/server/api/microservice/extensions/{download.post.js → download.post.ts} +13 -6
  303. package/server/api/serverless/run_cloud.post.ts +92 -0
  304. package/server/utils/{app_config.js → app_config.ts} +40 -18
  305. package/server/utils/{cleanup.js → cleanup.ts} +76 -29
  306. package/server/utils/{cloud.js → cloud.ts} +33 -17
  307. package/server/utils/{extension.js → extension.ts} +31 -4
  308. package/server/utils/{microservices.js → microservices.ts} +68 -27
  309. package/server/utils/{path.js → path.ts} +36 -17
  310. package/server/utils/{scripts.js → scripts.ts} +49 -33
  311. package/server/utils/{server.js → server.ts} +13 -6
  312. package/server/utils/server_config.ts +74 -0
  313. package/server/utils/stream.ts +6 -0
  314. package/server/utils/ws_client.ts +165 -0
  315. package/shared/{scripts.js → scripts.ts} +15 -10
  316. package/shared/utils/call_raw.ts +73 -0
  317. package/shared/utils/{call_schema.js → call_schema.ts} +15 -6
  318. package/shared/utils/fetch_raw.ts +125 -0
  319. package/shared/utils/{fetch_schema.js → fetch_schema.ts} +16 -7
  320. package/shared/utils/file.ts +22 -0
  321. package/shared/utils/{parse_boolean.js → parse_boolean.ts} +1 -1
  322. package/shared/utils/response_handlers/load.ts +109 -0
  323. package/shared/utils/types.ts +27 -0
  324. package/shared/utils/{validate_schema.js → validate_schema.ts} +3 -1
  325. package/.github/workflows/config.json +0 -5
  326. package/.github/workflows/deploy.yml +0 -15
  327. package/.github/workflows/manual_release.yml +0 -11
  328. package/.github/workflows/merge_request.yml +0 -9
  329. package/.github/workflows/pr_update.yml +0 -11
  330. package/.github/workflows/prepare_deploy.yml +0 -9
  331. package/.github/workflows/schedule.yml +0 -18
  332. package/.github/workflows/test.yml +0 -14
  333. package/.github/workflows/test_pr.yml +0 -12
  334. package/.oxlintrc.json +0 -150
  335. package/.releaserc +0 -11
  336. package/app/components/Viewer/ObjectTree/Views/ModelComponents.vue +0 -224
  337. package/app/composables/clipping_planes_widget.js +0 -249
  338. package/app/composables/global_attribute_style.js +0 -181
  339. package/app/composables/hover_highlight.js +0 -91
  340. package/app/composables/responsive_middle_truncate.js +0 -34
  341. package/app/composables/stepper_tree.js +0 -56
  342. package/app/composables/tree_filter.js +0 -138
  343. package/app/composables/use_adaptive_styles.js +0 -120
  344. package/app/composables/use_overlapping_picker.js +0 -169
  345. package/app/composables/use_quick_colormap.js +0 -32
  346. package/app/composables/virtual_tree.js +0 -191
  347. package/app/stores/app.js +0 -326
  348. package/app/stores/camera_manager.js +0 -57
  349. package/app/stores/data.js +0 -278
  350. package/app/stores/data_helpers/collections.js +0 -96
  351. package/app/stores/data_helpers/mesh.js +0 -122
  352. package/app/stores/data_style.js +0 -116
  353. package/app/stores/infra.js +0 -95
  354. package/app/stores/treeview.js +0 -290
  355. package/app/utils/attributes.js +0 -23
  356. package/app/utils/clipping_planes.js +0 -110
  357. package/app/utils/colormap.js +0 -64
  358. package/app/utils/default_styles/meshes.js +0 -191
  359. package/app/utils/status.js +0 -10
  360. package/commitlint.config.js +0 -20
  361. package/internal/database/database.js +0 -80
  362. package/internal/database/tables/camera_positions.js +0 -4
  363. package/internal/database/tables/data_style.js +0 -4
  364. package/internal/database/tables/model_component_datastyle.js +0 -4
  365. package/internal/database/tables/model_component_type_datastyle.js +0 -4
  366. package/internal/database/tables/model_components.js +0 -4
  367. package/internal/database/tables/model_components_relation.js +0 -4
  368. package/internal/stores/data_style/mesh/cells/cell.js +0 -196
  369. package/internal/stores/data_style/mesh/cells/common.js +0 -39
  370. package/internal/stores/data_style/mesh/cells/index.js +0 -81
  371. package/internal/stores/data_style/mesh/cells/vertex.js +0 -193
  372. package/internal/stores/data_style/mesh/cells/visibility.js +0 -35
  373. package/internal/stores/data_style/mesh/edges/common.js +0 -32
  374. package/internal/stores/data_style/mesh/edges/edge.js +0 -195
  375. package/internal/stores/data_style/mesh/edges/index.js +0 -81
  376. package/internal/stores/data_style/mesh/edges/vertex.js +0 -196
  377. package/internal/stores/data_style/mesh/edges/visibility.js +0 -34
  378. package/internal/stores/data_style/mesh/edges/width.js +0 -34
  379. package/internal/stores/data_style/mesh/points/common.js +0 -37
  380. package/internal/stores/data_style/mesh/points/index.js +0 -82
  381. package/internal/stores/data_style/mesh/points/size.js +0 -35
  382. package/internal/stores/data_style/mesh/points/vertex.js +0 -193
  383. package/internal/stores/data_style/mesh/points/visibility.js +0 -37
  384. package/internal/stores/data_style/mesh/polygons/common.js +0 -32
  385. package/internal/stores/data_style/mesh/polygons/index.js +0 -107
  386. package/internal/stores/data_style/mesh/polygons/polygon.js +0 -196
  387. package/internal/stores/data_style/mesh/polygons/vertex.js +0 -196
  388. package/internal/stores/data_style/mesh/polygons/visibility.js +0 -38
  389. package/internal/stores/data_style/mesh/polyhedra/common.js +0 -32
  390. package/internal/stores/data_style/mesh/polyhedra/index.js +0 -98
  391. package/internal/stores/data_style/mesh/polyhedra/polyhedron.js +0 -196
  392. package/internal/stores/data_style/mesh/polyhedra/vertex.js +0 -196
  393. package/internal/stores/data_style/mesh/polyhedra/visibility.js +0 -38
  394. package/internal/stores/data_style/model/blocks/common.js +0 -51
  395. package/internal/stores/data_style/model/blocks/polyhedron.js +0 -215
  396. package/internal/stores/data_style/model/blocks/vertex.js +0 -204
  397. package/internal/stores/data_style/model/blocks/visibility.js +0 -20
  398. package/internal/stores/data_style/model/color.js +0 -218
  399. package/internal/stores/data_style/model/common.js +0 -141
  400. package/internal/stores/data_style/model/corners/common.js +0 -51
  401. package/internal/stores/data_style/model/corners/vertex.js +0 -204
  402. package/internal/stores/data_style/model/corners/visibility.js +0 -20
  403. package/internal/stores/data_style/model/edges/common.js +0 -20
  404. package/internal/stores/data_style/model/edges/visibility.js +0 -38
  405. package/internal/stores/data_style/model/lines/common.js +0 -51
  406. package/internal/stores/data_style/model/lines/edge.js +0 -203
  407. package/internal/stores/data_style/model/lines/vertex.js +0 -204
  408. package/internal/stores/data_style/model/lines/visibility.js +0 -20
  409. package/internal/stores/data_style/model/points/common.js +0 -20
  410. package/internal/stores/data_style/model/points/index.js +0 -25
  411. package/internal/stores/data_style/model/points/size.js +0 -36
  412. package/internal/stores/data_style/model/points/visibility.js +0 -36
  413. package/internal/stores/data_style/model/selection.js +0 -89
  414. package/internal/stores/data_style/model/surfaces/common.js +0 -51
  415. package/internal/stores/data_style/model/surfaces/polygon.js +0 -215
  416. package/internal/stores/data_style/model/surfaces/vertex.js +0 -215
  417. package/internal/stores/data_style/model/surfaces/visibility.js +0 -20
  418. package/internal/stores/data_style/state.js +0 -197
  419. package/internal/stores/hybrid_viewer/brightness.js +0 -82
  420. package/internal/stores/hybrid_viewer/camera.js +0 -274
  421. package/internal/stores/hybrid_viewer/highlight.js +0 -170
  422. package/internal/stores/hybrid_viewer/scene.js +0 -136
  423. package/internal/stores/hybrid_viewer/viewport.js +0 -140
  424. package/internal/utils/api_fetch.js +0 -52
  425. package/internal/utils/upload_file.js +0 -57
  426. package/internal/utils/viewer_call.js +0 -49
  427. package/internal/utils/ws_client.js +0 -29
  428. package/nuxt.config.js +0 -106
  429. package/scripts/generate_geode_objects.js +0 -24
  430. package/server/api/local/app/project_folder_path.post.js +0 -29
  431. package/server/api/local/app/run_back.post.js +0 -33
  432. package/server/api/local/app/run_viewer.post.js +0 -33
  433. package/server/api/local/extensions/upload.put.js +0 -72
  434. package/server/api/microservice/app/set_app_base_url.post.js +0 -25
  435. package/server/api/microservice/app/set_back_base_url.post.js +0 -22
  436. package/server/api/microservice/app/set_is_app_ready.post.js +0 -25
  437. package/server/api/microservice/app/set_viewer_base_url.post.js +0 -22
  438. package/server/api/serverless/run_cloud.post.js +0 -44
  439. package/server/utils/server_config.js +0 -58
  440. package/server/utils/ws_client.js +0 -112
  441. package/shared/utils/call_raw.js +0 -46
  442. package/shared/utils/fetch_raw.js +0 -61
  443. package/shared/utils/file.js +0 -16
  444. package/shared/utils/response_handlers/load.js +0 -74
  445. package/tests/integration/data/uploads/test.og_brep +0 -0
  446. package/tests/integration/data/uploads/test.og_edc2d +0 -0
  447. package/tests/integration/data/uploads/test.og_edc3d +0 -0
  448. package/tests/integration/data/uploads/test.og_psf3d +0 -0
  449. package/tests/integration/data/uploads/test.og_rgd2d +0 -0
  450. package/tests/integration/data/uploads/test.og_rgd3d +0 -0
  451. package/tests/integration/data/uploads/test.vtu +0 -22
  452. package/tests/integration/setup.js +0 -92
  453. package/tests/integration/stores/data_style/mesh/cells.nuxt.test.js +0 -343
  454. package/tests/integration/stores/data_style/mesh/edges.nuxt.test.js +0 -254
  455. package/tests/integration/stores/data_style/mesh/index.nuxt.test.js +0 -62
  456. package/tests/integration/stores/data_style/mesh/points.nuxt.test.js +0 -201
  457. package/tests/integration/stores/data_style/mesh/polygons.nuxt.test.js +0 -260
  458. package/tests/integration/stores/data_style/mesh/polyhedra.nuxt.test.js +0 -267
  459. package/tests/integration/stores/data_style/model/blocks.nuxt.test.js +0 -397
  460. package/tests/integration/stores/data_style/model/corners.nuxt.test.js +0 -264
  461. package/tests/integration/stores/data_style/model/edges.nuxt.test.js +0 -71
  462. package/tests/integration/stores/data_style/model/index.nuxt.test.js +0 -92
  463. package/tests/integration/stores/data_style/model/lines.nuxt.test.js +0 -379
  464. package/tests/integration/stores/data_style/model/points.nuxt.test.js +0 -95
  465. package/tests/integration/stores/data_style/model/surfaces.nuxt.test.js +0 -574
  466. package/tests/integration/stores/viewer.nuxt.test.js +0 -69
  467. package/tests/setup_indexeddb.js +0 -4
  468. package/tests/unit/components/CrsSelector.nuxt.test.js +0 -55
  469. package/tests/unit/components/DragAndDrop.nuxt.test.js +0 -89
  470. package/tests/unit/components/ExtensionSelector.nuxt.test.js +0 -65
  471. package/tests/unit/components/FeedBack/ErrorsBanner.nuxt.test.js +0 -41
  472. package/tests/unit/components/FeedBack/Snackers.nuxt.test.js +0 -49
  473. package/tests/unit/components/FileSelector.nuxt.test.js +0 -124
  474. package/tests/unit/components/FileUploader.nuxt.test.js +0 -69
  475. package/tests/unit/components/MissingFilesSelector.nuxt.test.js +0 -77
  476. package/tests/unit/components/ObjectSelector.nuxt.test.js +0 -118
  477. package/tests/unit/components/PackagesVersions.nuxt.test.js +0 -42
  478. package/tests/unit/components/Step.nuxt.test.js +0 -51
  479. package/tests/unit/components/Stepper.nuxt.test.js +0 -41
  480. package/tests/unit/components/ToolPanel.nuxt.test.js +0 -66
  481. package/tests/unit/composables/api_fetch.nuxt.test.js +0 -75
  482. package/tests/unit/composables/project_manager.nuxt.test.js +0 -299
  483. package/tests/unit/composables/run_function_when_microservices_connected.nuxt.test.js +0 -57
  484. package/tests/unit/composables/upload_file.nuxt.test.js +0 -45
  485. package/tests/unit/composables/virtual_tree.nuxt.test.js +0 -63
  486. package/tests/unit/plugins/project_load.nuxt.test.js +0 -98
  487. package/tests/unit/stores/app.nuxt.test.js +0 -189
  488. package/tests/unit/stores/back.nuxt.test.js +0 -147
  489. package/tests/unit/stores/cloud.nuxt.test.js +0 -90
  490. package/tests/unit/stores/data.nuxt.test.js +0 -162
  491. package/tests/unit/stores/feedback.nuxt.test.js +0 -90
  492. package/tests/unit/stores/infra.nuxt.test.js +0 -313
  493. package/tests/unit/stores/treeview.nuxt.test.js +0 -63
  494. package/tests/unit/stores/viewer.nuxt.test.js +0 -161
  495. package/tests/unit/utils/validate_schema.nuxt.test.js +0 -38
  496. package/tests/utils.js +0 -20
  497. package/tests/vitest.config.js +0 -67
  498. /package/server/api/local/app/{kill.post.js → kill.post.ts} +0 -0
  499. /package/shared/{app_mode.js → app_mode.ts} +0 -0
@@ -2,20 +2,27 @@
2
2
  import { promises as fs } from "node:fs";
3
3
 
4
4
  // Third party imports
5
- import { createError, defineEventHandler, readBody } from "h3";
5
+ import { type H3Event, createError, defineEventHandler, readBody } from "h3";
6
6
 
7
7
  // Local imports
8
8
  import {
9
9
  registerExtensionFile,
10
10
  targetExtensionFilePath,
11
- } from "@geode/opengeodeweb-front/server/utils/app_config.js";
11
+ } from "@geode/opengeodeweb-front/server/utils/app_config.ts";
12
12
 
13
- export default defineEventHandler(async (event) => {
13
+ interface DownloadExtensionBody {
14
+ projectName: string;
15
+ url: string;
16
+ extensionFileName: string;
17
+ }
18
+
19
+ export default defineEventHandler(async (event: H3Event) => {
14
20
  try {
15
- const body = await readBody(event);
21
+ const body = await readBody<DownloadExtensionBody>(event);
16
22
  const { projectName, url, extensionFileName } = body;
17
23
  console.log({ projectName, url, extensionFileName });
18
- const fileBuffer = await fetch(url).then((file) => file.arrayBuffer());
24
+ const response: Response = await fetch(url);
25
+ const fileBuffer = await response.arrayBuffer();
19
26
  const filePath = targetExtensionFilePath(projectName, extensionFileName);
20
27
  await fs.writeFile(filePath, Buffer.from(fileBuffer));
21
28
  await registerExtensionFile(projectName, filePath);
@@ -26,7 +33,7 @@ export default defineEventHandler(async (event) => {
26
33
  console.error("Error downloading extension:", error);
27
34
  throw createError({
28
35
  statusCode: 500,
29
- statusMessage: error.message,
36
+ statusMessage: error instanceof Error ? error.message : String(error),
30
37
  });
31
38
  }
32
39
  });
@@ -0,0 +1,92 @@
1
+ // Node imports
2
+
3
+ // Third party imports
4
+ import { GoogleAuth, type JWTInput } from "google-auth-library";
5
+ import { type H3Event, createError, defineEventHandler, readBody } from "h3";
6
+ import { ServicesClient } from "@google-cloud/run";
7
+
8
+ // Local imports
9
+ import { artifactImage, requestConfig } from "@geode/opengeodeweb-front/server/utils/cloud.ts";
10
+
11
+ interface RunCloudBody {
12
+ email: string;
13
+ }
14
+
15
+ function isServiceAccountCredentials(value: unknown): value is JWTInput {
16
+ return (
17
+ typeof value === "object" && value !== null && "client_email" in value && "private_key" in value
18
+ );
19
+ }
20
+
21
+ export default defineEventHandler(async (event: H3Event) => {
22
+ try {
23
+ const { email } = await readBody<RunCloudBody>(event);
24
+ console.log("[RUN CLOUD] Received request to create backend for email:", email);
25
+
26
+ const { GOOGLE_CLOUD_KEY, GOOGLE_CLOUD_PROJECT, PROJECT } = process.env;
27
+
28
+ if (
29
+ GOOGLE_CLOUD_KEY === undefined ||
30
+ GOOGLE_CLOUD_KEY === "" ||
31
+ GOOGLE_CLOUD_PROJECT === undefined ||
32
+ GOOGLE_CLOUD_PROJECT === "" ||
33
+ PROJECT === undefined ||
34
+ PROJECT === ""
35
+ ) {
36
+ throw createError({
37
+ statusCode: 500,
38
+ statusMessage:
39
+ "Missing required environment variables: GOOGLE_CLOUD_KEY, GOOGLE_CLOUD_PROJECT, or PROJECT",
40
+ });
41
+ }
42
+
43
+ const projectId: string = GOOGLE_CLOUD_PROJECT;
44
+ const projectName: string = PROJECT;
45
+
46
+ const parsedKey: unknown = JSON.parse(GOOGLE_CLOUD_KEY);
47
+ if (!isServiceAccountCredentials(parsedKey)) {
48
+ throw createError({
49
+ statusCode: 500,
50
+ statusMessage: "GOOGLE_CLOUD_KEY is not a valid service account credentials JSON",
51
+ });
52
+ }
53
+ const credentials: JWTInput = parsedKey;
54
+
55
+ const location = "europe-west9";
56
+ const parent = `projects/${projectId}/locations/${location}`;
57
+ console.log({ parent });
58
+
59
+ const auth = new GoogleAuth({
60
+ // oxlint-disable-next-line typescript/no-deprecated
61
+ credentials,
62
+ scopes: ["https://www.googleapis.com/auth/cloud-platform"],
63
+ });
64
+ const authClient = await auth.getClient();
65
+ const image = await artifactImage(parent, authClient);
66
+ const request = requestConfig(parent, image, email, projectName);
67
+ console.log({ request });
68
+
69
+ const runClient = new ServicesClient({ authClient });
70
+ const [operation] = await runClient.createService(request);
71
+ const [response] = await operation.promise();
72
+
73
+ if (response.uri === null || response.uri === undefined || response.uri === "") {
74
+ throw createError({
75
+ statusCode: 500,
76
+ statusMessage: "Cloud Run service created but no URI was returned",
77
+ });
78
+ }
79
+
80
+ console.log("Service URL created:", response.uri);
81
+ return {
82
+ statusCode: 200,
83
+ url: response.uri.replace(/^https?:\/\//iu, ""),
84
+ };
85
+ } catch (error) {
86
+ console.log(error);
87
+ throw createError({
88
+ statusCode: 500,
89
+ statusMessage: error instanceof Error ? error.message : String(error),
90
+ });
91
+ }
92
+ });
@@ -1,6 +1,6 @@
1
1
  // Node.js imports
2
2
  import path from "node:path";
3
- import { unlink } from "node:fs";
3
+ import { unlink } from "node:fs/promises";
4
4
 
5
5
  // Third party imports
6
6
  import Conf from "conf";
@@ -9,8 +9,12 @@ import sanitize from "sanitize-filename";
9
9
 
10
10
  // Local imports
11
11
 
12
- function projectConf(projectName) {
13
- const projectConfig = new Conf({
12
+ interface ExtensionsConfigSchema {
13
+ extensions: Record<string, { path: string }>;
14
+ }
15
+
16
+ function projectConf(projectName: string): Conf<ExtensionsConfigSchema> {
17
+ const projectConfig = new Conf<ExtensionsConfigSchema>({
14
18
  projectName,
15
19
  });
16
20
  console.log(projectConf.name, {
@@ -18,16 +22,19 @@ function projectConf(projectName) {
18
22
  });
19
23
  return projectConfig;
20
24
  }
21
- function confFolderPath(projectName) {
25
+
26
+ function confFolderPath(projectName: string): string {
22
27
  const projectConfig = projectConf(projectName);
23
28
  return path.dirname(projectConfig.path);
24
29
  }
25
- function targetExtensionFilePath(projectName, filename) {
30
+
31
+ function targetExtensionFilePath(projectName: string, filename: string): string {
26
32
  const safeFilename = sanitize(filename);
27
33
  const targetPath = path.join(confFolderPath(projectName), safeFilename);
28
34
  return targetPath;
29
35
  }
30
- function extensionsConf(projectName) {
36
+
37
+ function extensionsConf(projectName: string): ExtensionsConfigSchema["extensions"] {
31
38
  const projectConfig = projectConf(projectName);
32
39
  if (!projectConfig.has("extensions")) {
33
40
  projectConfig.set("extensions", {});
@@ -35,43 +42,58 @@ function extensionsConf(projectName) {
35
42
  const extensionsConfig = projectConfig.get("extensions");
36
43
  return extensionsConfig;
37
44
  }
38
- function addExtensionToConf(projectName, { extensionId, extensionPath }) {
45
+
46
+ function addExtensionToConf(
47
+ projectName: string,
48
+ { extensionId, extensionPath }: { extensionId: string; extensionPath: string },
49
+ ): void {
39
50
  const projectConfig = projectConf(projectName);
40
51
  projectConfig.set(`extensions.${extensionId}.path`, extensionPath);
41
52
  }
42
53
 
43
- function extensionPathFromConf(projectName, extensionId) {
54
+ function extensionPathFromConf(projectName: string, extensionId: string): string {
44
55
  const projectConfig = projectConf(projectName);
45
56
  return projectConfig.get(`extensions.${extensionId}.path`);
46
57
  }
47
58
 
48
- async function removeExtensionFromConf(projectName, extensionId) {
59
+ async function removeExtensionFromConf(projectName: string, extensionId: string): Promise<void> {
49
60
  const projectConfig = projectConf(projectName);
50
61
  const extensionArchivePath = extensionPathFromConf(projectName, extensionId);
51
- await unlink(extensionArchivePath, (error) => {
52
- if (error) {
53
- throw error;
54
- }
55
- console.log(`${extensionArchivePath} was deleted`);
56
- });
62
+ await unlink(extensionArchivePath);
63
+ console.log(`${extensionArchivePath} was deleted`);
57
64
  projectConfig.delete(`extensions.${extensionId}`);
58
65
  console.log(`${extensionId} was deleted from ${projectName} config`);
59
66
  }
60
67
 
61
- async function registerExtensionFile(projectName, file) {
68
+ interface ExtensionMetadata {
69
+ id: string;
70
+ [key: string]: unknown;
71
+ }
72
+
73
+ function isExtensionMetadata(value: unknown): value is ExtensionMetadata {
74
+ return (
75
+ typeof value === "object" && value !== null && "id" in value && typeof value.id === "string"
76
+ );
77
+ }
78
+
79
+ async function registerExtensionFile(projectName: string, file: string): Promise<void> {
62
80
  const StreamZipAsync = StreamZip.async;
63
81
  const zip = new StreamZipAsync({
64
82
  file,
65
83
  storeEntries: true,
66
84
  });
67
85
  const metadataJson = await zip.entryData("metadata.json");
68
- const metadata = JSON.parse(metadataJson);
69
- const { id } = metadata;
86
+ const parsedMetadata: unknown = JSON.parse(metadataJson.toString("utf8"));
87
+ if (!isExtensionMetadata(parsedMetadata)) {
88
+ throw new TypeError("metadata.json does not match the expected ExtensionMetadata shape");
89
+ }
90
+ const { id } = parsedMetadata;
70
91
  addExtensionToConf(projectName, {
71
92
  extensionId: id,
72
93
  extensionPath: file,
73
94
  });
74
95
  }
96
+
75
97
  export {
76
98
  addExtensionToConf,
77
99
  confFolderPath,
@@ -8,8 +8,17 @@ import { WebSocket } from "ws";
8
8
  import pTimeout from "p-timeout";
9
9
  import { rimraf } from "rimraf";
10
10
 
11
+ interface Microservice {
12
+ type: "back" | "viewer";
13
+ name: string;
14
+ port: number;
15
+ url?: string;
16
+ method?: string;
17
+ }
18
+
11
19
  const MAX_DELETE_FOLDER_RETRIES = 5;
12
- async function deleteFolderRecursive(folderPath) {
20
+
21
+ async function deleteFolderRecursive(folderPath: string): Promise<void> {
13
22
  if (!fs.existsSync(folderPath)) {
14
23
  console.log(`Folder ${folderPath} does not exist.`);
15
24
  return;
@@ -23,7 +32,6 @@ async function deleteFolderRecursive(folderPath) {
23
32
  return;
24
33
  } catch (error) {
25
34
  console.error(`Error deleting folder ${folderPath}:`, error);
26
- // Wait before retrying
27
35
  const MILLISECONDS_PER_RETRY = 1000;
28
36
  const DELAY = MILLISECONDS_PER_RETRY * (i + 1);
29
37
  // oxlint-disable-next-line no-await-in-loop
@@ -35,35 +43,54 @@ async function deleteFolderRecursive(folderPath) {
35
43
  `Failed to delete folder ${folderPath} after ${MAX_DELETE_FOLDER_RETRIES} retries`,
36
44
  );
37
45
  }
38
- function killHttpMicroservice(microservice) {
46
+
47
+ function isErrorWithMessage(error: unknown): error is { message: string } {
48
+ return (
49
+ typeof error === "object" &&
50
+ error !== null &&
51
+ "message" in error &&
52
+ typeof error.message === "string"
53
+ );
54
+ }
55
+
56
+ async function killHttpMicroservice(microservice: Microservice): Promise<void> {
39
57
  console.log("killHttpMicroservice", {
40
58
  ...microservice,
41
59
  });
42
60
  const failMessage = `Failed to kill ${microservice.name}`;
43
- async function do_kill() {
61
+ async function do_kill(): Promise<void> {
62
+ if (microservice.url === undefined) {
63
+ return;
64
+ }
44
65
  try {
45
66
  await fetch(microservice.url, {
46
67
  method: microservice.method,
47
68
  });
48
69
  } catch (error) {
49
- console.log(`Expected error during kill of ${microservice.name}:`, error.message);
70
+ const message = isErrorWithMessage(error) ? error.message : String(error);
71
+ console.log(`Expected error during kill of ${microservice.name}:`, message);
50
72
  }
51
73
  }
52
- return pTimeout(do_kill(), {
74
+ await pTimeout(do_kill(), {
53
75
  milliseconds: 5000,
54
76
  message: failMessage,
55
77
  });
56
78
  }
57
- function killWebsocketMicroservice(microservice) {
79
+
80
+ async function killWebsocketMicroservice(microservice: Microservice): Promise<void> {
58
81
  console.log("killWebsocketMicroservice", {
59
82
  ...microservice,
60
83
  });
61
84
  const failMessage = `Failed to kill ${microservice.name}`;
62
85
  const successMessage = `Disconnected from ${microservice.name} WebSocket server`;
63
- function do_kill() {
86
+ async function do_kill(): Promise<void> {
87
+ if (microservice.url === undefined) {
88
+ return;
89
+ }
90
+ const socketUrl = microservice.url;
64
91
  // oxlint-disable-next-line promise/avoid-new
65
- return new Promise((resolve) => {
66
- const socket = new WebSocket(microservice.url);
92
+ await new Promise<void>((resolve) => {
93
+ const socket = new WebSocket(socketUrl);
67
94
  socket.on("open", () => {
68
95
  console.log("Connected to WebSocket server");
69
96
  socket.send(
@@ -78,7 +105,7 @@ function killWebsocketMicroservice(microservice) {
78
105
  }),
79
106
  );
80
107
  });
81
- socket.on("message", (data) => {
108
+ socket.on("message", (data: Buffer | string) => {
82
109
  const message = data.toString();
83
110
  console.log("Received from server:", message);
84
111
  if (message.includes("hello")) {
@@ -97,45 +124,55 @@ function killWebsocketMicroservice(microservice) {
97
124
  console.log(successMessage);
98
125
  resolve();
99
126
  });
100
- socket.on("error", (error) => {
127
+ socket.on("error", (error: Error) => {
101
128
  console.error("WebSocket error:", error);
102
129
  socket.close();
103
130
  resolve();
104
131
  });
105
132
  });
106
133
  }
107
- return pTimeout(do_kill(), {
134
+ await pTimeout(do_kill(), {
108
135
  milliseconds: 5000,
109
136
  message: failMessage,
110
137
  });
111
138
  }
112
- async function killMicroservice(microservice) {
139
+
140
+ async function killMicroservice(microservice: Microservice): Promise<void> {
113
141
  if (microservice.type === "back") {
114
142
  await killHttpMicroservice(microservice);
115
143
  } else if (microservice.type === "viewer") {
116
144
  await killWebsocketMicroservice(microservice);
117
145
  } else {
118
- throw new Error(`Unknown microservice type: ${microservice.type}`);
146
+ const exhaustiveCheck: never = microservice.type;
147
+ throw new Error(`Unknown microservice type: ${String(exhaustiveCheck)}`);
119
148
  }
120
149
  }
121
- async function killMicroservices(microservices) {
150
+
151
+ async function killMicroservices(microservices: readonly Microservice[]): Promise<Microservice[]> {
122
152
  console.log("killMicroservices", {
123
153
  microservices,
124
154
  });
125
155
  const results = await Promise.allSettled(
126
- microservices.map((microservice) => killMicroservice(microservice)),
156
+ microservices.map(async (microservice) => {
157
+ await killMicroservice(microservice);
158
+ }),
127
159
  );
128
- const killed = microservices.filter((_, index) => results[index].status === "fulfilled");
129
- for (let i = 0; i < killed.length; i += 1) {
130
- const microservice = microservices[i];
131
- microservices.splice(microservices.indexOf(microservice), 1);
132
- }
160
+ return microservices.filter((_, index) => results[index]?.status !== "fulfilled");
133
161
  }
134
- function microservicesMetadatasPath(projectFolderPath) {
162
+
163
+ function microservicesMetadatasPath(projectFolderPath: string): string {
135
164
  return path.join(projectFolderPath, "microservices.json");
136
165
  }
137
166
 
138
- function projectMicroservices(projectFolderPath) {
167
+ function isMicroservicesMetadatas(value: unknown): value is { microservices: Microservice[] } {
168
+ return (
169
+ typeof value === "object" &&
170
+ value !== null &&
171
+ Array.isArray((value as { microservices?: unknown }).microservices)
172
+ );
173
+ }
174
+
175
+ function projectMicroservices(projectFolderPath: string): Microservice[] {
139
176
  console.log("projectMicroservices", {
140
177
  projectFolderPath,
141
178
  });
@@ -146,10 +183,14 @@ function projectMicroservices(projectFolderPath) {
146
183
  };
147
184
  fs.writeFileSync(filePath, JSON.stringify(microservicesMetadatas, undefined, 2), "utf8");
148
185
  }
149
- const content = JSON.parse(fs.readFileSync(filePath, "utf8"));
150
- return content.microservices;
186
+ const parsed: unknown = JSON.parse(fs.readFileSync(filePath, "utf8"));
187
+ if (!isMicroservicesMetadatas(parsed)) {
188
+ throw new Error(`Invalid microservices metadata file: ${filePath}`);
189
+ }
190
+ return parsed.microservices;
151
191
  }
152
- async function cleanupBackend(projectFolderPath) {
192
+
193
+ async function cleanupBackend(projectFolderPath: string): Promise<void> {
153
194
  if (!fs.existsSync(projectFolderPath)) {
154
195
  console.log(`Folder ${projectFolderPath} does not exist. Skipping cleanup.`);
155
196
  return;
@@ -158,8 +199,13 @@ async function cleanupBackend(projectFolderPath) {
158
199
  await killMicroservices(microservices);
159
200
  await deleteFolderRecursive(projectFolderPath);
160
201
  }
161
- function getMicroserviceByName(microservices, name) {
162
- return microservices.find((microservice) => microservice.name === name);
202
+
203
+ function getMicroserviceByName(
204
+ microservices: readonly Microservice[],
205
+ name: string,
206
+ ): Microservice | undefined {
207
+ const found = microservices.find((microservice) => microservice.name === name);
208
+ return found === undefined ? undefined : { ...found };
163
209
  }
164
210
 
165
211
  export {
@@ -170,3 +216,4 @@ export {
170
216
  projectMicroservices,
171
217
  getMicroserviceByName,
172
218
  };
219
+ export type { Microservice };
@@ -4,20 +4,26 @@ import fs from "node:fs";
4
4
  import path from "node:path";
5
5
 
6
6
  // Third party imports
7
+ import type { AuthClient, OAuth2Client } from "google-auth-library";
7
8
  import { google } from "googleapis";
9
+ import type { protos } from "@google-cloud/run";
8
10
 
9
11
  // Local imports
10
12
 
13
+ // oxlint-disable-next-line eslint/id-length
14
+ type CreateServiceRequest = protos.google.cloud.run.v2.ICreateServiceRequest;
15
+
11
16
  const LOCATIONS_DIR = "/etc/nginx/locations";
12
17
 
13
- async function artifactImage(parent, authClient) {
18
+ async function artifactImage(parent: string, authClient: AuthClient): Promise<string> {
14
19
  const projectName = process.env.PROJECT;
15
20
  const registry = google.artifactregistry({
16
21
  version: "v1",
17
- auth: authClient,
22
+ // oxlint-disable-next-line typescript/no-unsafe-type-assertion
23
+ auth: authClient as OAuth2Client,
18
24
  });
19
25
  const branch = process.env.NETLIFY_BRANCH;
20
- const [_, projectId] = parent.split("/");
26
+ const [, projectId] = parent.split("/");
21
27
  const repository = `${parent}/repositories/github/packages/`;
22
28
  const name = `${repository}${projectName}/tags/${branch}`;
23
29
  console.log({ name });
@@ -25,14 +31,15 @@ async function artifactImage(parent, authClient) {
25
31
  name,
26
32
  });
27
33
  console.log({ response });
28
- const digest = response.data.version.split("/").pop();
34
+ const version = response.data.version ?? "";
35
+ const digest = version.split("/").pop();
29
36
  const artifactRegistry = `europe-west9-docker.pkg.dev/${projectId}/github`;
30
37
  const image = `${artifactRegistry}/${projectName}@${digest}`;
31
38
  console.log("Found image for", projectName, image);
32
39
  return image;
33
40
  }
34
41
 
35
- function sanitizeLabelValue(label) {
42
+ function sanitizeLabelValue(label: string): string {
36
43
  console.log("label", label);
37
44
  const maxLabelLength = 63;
38
45
  return label
@@ -41,14 +48,19 @@ function sanitizeLabelValue(label) {
41
48
  .slice(0, maxLabelLength);
42
49
  }
43
50
 
44
- function requestConfig(parent, image, email, projectName) {
51
+ function requestConfig(
52
+ parent: string,
53
+ image: string,
54
+ email: string,
55
+ projectName: string,
56
+ ): CreateServiceRequest {
45
57
  const resources = {
46
58
  limits: {
47
59
  cpu: "2000m",
48
60
  memory: "3Gi",
49
61
  },
50
62
  cpuIdle: false,
51
- startup_cpu_boost: true,
63
+ startupCpuBoost: true,
52
64
  };
53
65
  const labels = {
54
66
  user: sanitizeLabelValue(email),
@@ -97,7 +109,11 @@ function requestConfig(parent, image, email, projectName) {
97
109
  };
98
110
  }
99
111
 
100
- function addSupervisorProgram(name, command, executableArgs) {
112
+ function addSupervisorProgram(
113
+ name: string,
114
+ command: string,
115
+ executableArgs: readonly string[],
116
+ ): void {
101
117
  const conf = `
102
118
  [program:${name}]
103
119
  command=${command} ${executableArgs.join(" ")}
@@ -116,7 +132,7 @@ stderr_logfile_maxbytes=0
116
132
  console.log("addSupervisorProgram", stdout);
117
133
  }
118
134
 
119
- function buildLocationBlock(routePath, port) {
135
+ function buildLocationBlock(routePath: string, port: number): string {
120
136
  if (!routePath.startsWith("/") || !routePath.endsWith("/")) {
121
137
  throw new Error(`routePath must start and end with '/', got: ${routePath}`);
122
138
  }
@@ -139,16 +155,16 @@ location ~ "^${routePath}" {
139
155
  add_header 'Content-Length' 0;
140
156
  return 204;
141
157
  }
142
-
158
+
143
159
  limit_except ${limitMethods} { deny all; }
144
-
160
+
145
161
  add_header 'Access-Control-Allow-Origin' $allow_origin always;
146
162
  add_header 'Access-Control-Allow-Credentials' 'true' always;
147
163
  add_header 'Access-Control-Allow-Methods' '${methods}' always;
148
164
  add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-CSRF-Token' always;
149
165
  add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
150
166
  add_header 'Vary' 'Origin' always;
151
-
167
+
152
168
  rewrite "^${routePath}(.*)" /$1 break;
153
169
  proxy_pass http://localhost:${port};
154
170
  proxy_http_version 1.1;
@@ -160,16 +176,16 @@ location ~ "^${routePath}" {
160
176
  `;
161
177
  }
162
178
 
163
- function nginxConfigFile(name) {
179
+ function nginxConfigFile(name: string): string {
164
180
  return path.join(LOCATIONS_DIR, `${name}.conf`);
165
181
  }
166
182
 
167
- function nginxReload() {
183
+ function nginxReload(): void {
168
184
  execFileSync("nginx", ["-t"]);
169
185
  execFileSync("nginx", ["-s", "reload"]);
170
186
  }
171
187
 
172
- function addNginxLocation(name, port) {
188
+ function addNginxLocation(name: string, port: number): string {
173
189
  fs.mkdirSync(LOCATIONS_DIR, { recursive: true });
174
190
  const filePath = nginxConfigFile(name);
175
191
  if (fs.existsSync(filePath)) {
@@ -185,8 +201,8 @@ function addNginxLocation(name, port) {
185
201
  return filePath;
186
202
  }
187
203
 
188
- function removeNginxLocation(name) {
189
- const filePath = filePathFor(name);
204
+ function removeNginxLocation(name: string): boolean {
205
+ const filePath = nginxConfigFile(name);
190
206
  if (!fs.existsSync(filePath)) {
191
207
  return false;
192
208
  }
@@ -1,14 +1,27 @@
1
1
  // Node imports
2
2
  import { promises as fs } from "node:fs";
3
3
  import path from "node:path";
4
+ import { z } from "zod";
4
5
 
5
6
  // Third party imports
6
7
  import { createError } from "h3";
7
8
 
8
9
  // Local imports
9
- import { extensionFrontendPath } from "@geode/opengeodeweb-front/server/utils/path.js";
10
+ import { extensionFrontendPath } from "@geode/opengeodeweb-front/server/utils/path.ts";
10
11
 
11
- async function readExtensionMetadata(unzippedExtensionPath) {
12
+ const extensionMetadataSchema = z
13
+ .object({
14
+ id: z.string(),
15
+ name: z.string(),
16
+ version: z.string(),
17
+ frontendFile: z.string(),
18
+ backendExecutable: z.string(),
19
+ })
20
+ .loose();
21
+
22
+ type ExtensionMetadata = z.infer<typeof extensionMetadataSchema>;
23
+
24
+ async function readExtensionMetadata(unzippedExtensionPath: string): Promise<ExtensionMetadata> {
12
25
  const metadataPath = path.join(unzippedExtensionPath, "metadata.json");
13
26
  const metadataContent = await fs.readFile(metadataPath, "utf8");
14
27
  if (!metadataContent) {
@@ -17,7 +30,17 @@ async function readExtensionMetadata(unzippedExtensionPath) {
17
30
  statusMessage: "Invalid extension file: missing metadata.json",
18
31
  });
19
32
  }
20
- const metadata = JSON.parse(metadataContent);
33
+
34
+ const parsed: unknown = JSON.parse(metadataContent);
35
+ const result = extensionMetadataSchema.safeParse(parsed);
36
+ if (!result.success) {
37
+ throw createError({
38
+ statusCode: 400,
39
+ statusMessage: "Invalid extension file: malformed metadata.json",
40
+ });
41
+ }
42
+ const metadata = result.data;
43
+
21
44
  console.log("readExtensionMetadata", { metadata });
22
45
  if (!metadata.frontendFile) {
23
46
  throw createError({
@@ -35,7 +58,11 @@ async function readExtensionMetadata(unzippedExtensionPath) {
35
58
  return metadata;
36
59
  }
37
60
 
38
- async function readExtensionFrontend(unzippedExtensionPath, frontendFile, id) {
61
+ async function readExtensionFrontend(
62
+ unzippedExtensionPath: string,
63
+ frontendFile: string,
64
+ id: string,
65
+ ): Promise<string> {
39
66
  console.log("readExtensionFrontend", { id });
40
67
  const frontendFilePath = await extensionFrontendPath(
41
68
  unzippedExtensionPath,