@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.
- package/.build/opengeodeweb_front_schemas.js +175 -0
- package/.build/server/utils/app_config.js +57 -0
- package/.build/server/utils/cleanup.js +135 -0
- package/.build/server/utils/cloud.js +156 -0
- package/.build/server/utils/microservices.js +153 -0
- package/.build/server/utils/path.js +108 -0
- package/.build/server/utils/scripts.js +134 -0
- package/.build/server/utils/server.js +44 -0
- package/.build/server/utils/server_config.js +51 -0
- package/.build/server/utils/stream.js +6 -0
- package/.build/server/utils/ws_client.js +100 -0
- package/.build/shared/app_mode.js +8 -0
- package/.build/shared/scripts.js +49 -0
- package/.build/shared/utils/call_raw.js +31 -0
- package/.build/shared/utils/call_schema.js +28 -0
- package/.build/shared/utils/fetch_raw.js +52 -0
- package/.build/shared/utils/fetch_schema.js +32 -0
- package/.build/shared/utils/file.js +14 -0
- package/.build/shared/utils/parse_boolean.js +23 -0
- package/.build/shared/utils/response_handlers/load.js +50 -0
- package/.build/shared/utils/types.js +1 -0
- package/.build/shared/utils/validate_schema.js +17 -0
- package/README.md +8 -0
- package/app/assets/{geode_objects.js → geode_objects.ts} +8 -1
- package/app/components/ActionButton.vue +28 -12
- package/app/components/Basic/Slider.vue +2 -2
- package/app/components/Basic/Switch.vue +2 -2
- package/app/components/CameraManager/List.vue +11 -11
- package/app/components/CameraManager/Saver.vue +8 -4
- package/app/components/CameraManager.vue +24 -12
- package/app/components/CameraOrientation.vue +31 -17
- package/app/components/ClippingPlaneCard.vue +13 -12
- package/app/components/ClippingPlanes.vue +31 -21
- package/app/components/CrsSelector.vue +26 -18
- package/app/components/DeleteDialog.vue +18 -16
- package/app/components/DragAndDrop.vue +55 -37
- package/app/components/DragAndDropInternal/DragAndDropInline.vue +31 -16
- package/app/components/DragAndDropInternal/DragAndDropOverlay.vue +32 -19
- package/app/components/ExtensionSelector.vue +34 -18
- package/app/components/FeedBack/ErrorBanner.vue +4 -3
- package/app/components/FeedBack/Snackers.vue +6 -5
- package/app/components/FetchingData.vue +8 -12
- package/app/components/FileSelector.vue +27 -17
- package/app/components/FileUploader.vue +51 -30
- package/app/components/GlassCard.vue +17 -13
- package/app/components/HybridRenderingView.vue +25 -12
- package/app/components/HybridViewerTooltip.vue +28 -26
- package/app/components/InfraConnected.vue +1 -1
- package/app/components/Launcher.vue +12 -10
- package/app/components/Loading/EcoMessages.vue +24 -13
- package/app/components/Loading/Header.vue +6 -7
- package/app/components/Loading/Progress.vue +6 -7
- package/app/components/Loading.vue +10 -14
- package/app/components/MissingFilesSelector.vue +35 -19
- package/app/components/ObjectSelector.vue +37 -21
- package/app/components/PackagesVersions.vue +16 -8
- package/app/components/Recaptcha.vue +17 -23
- package/app/components/RemoteRenderingView.vue +21 -15
- package/app/components/Ruler.vue +11 -9
- package/app/components/Screenshot.vue +25 -19
- package/app/components/SearchBar.vue +12 -6
- package/app/components/ShrinkFilter.vue +19 -14
- package/app/components/Step.vue +32 -12
- package/app/components/Stepper.vue +19 -7
- package/app/components/ToolPanel.vue +29 -13
- package/app/components/ViewToolbar.vue +53 -44
- package/app/components/Viewer/ContextMenu/CenterButton.vue +16 -9
- package/app/components/Viewer/ContextMenu/CircularItems.vue +13 -10
- package/app/components/Viewer/ContextMenu/ContextMenu.vue +40 -32
- package/app/components/Viewer/ContextMenu/ContextMenuItem.vue +31 -17
- package/app/components/Viewer/ContextMenu/InfoCard.vue +38 -22
- package/app/components/Viewer/EdgedCurve/PointsOptions.vue +8 -5
- package/app/components/Viewer/EdgedCurve/SpecificEdgesOptions.vue +67 -48
- package/app/components/Viewer/Generic/Mesh/CellsOptions.vue +74 -50
- package/app/components/Viewer/Generic/Mesh/EdgesOptions.vue +69 -50
- package/app/components/Viewer/Generic/Mesh/PointsOptions.vue +47 -35
- package/app/components/Viewer/Generic/Mesh/PolygonsOptions.vue +91 -51
- package/app/components/Viewer/Generic/Mesh/PolyhedraOptions.vue +74 -49
- package/app/components/Viewer/Generic/Model/BlocksOptions.vue +115 -53
- package/app/components/Viewer/Generic/Model/CornersOptions.vue +75 -37
- package/app/components/Viewer/Generic/Model/EdgesOptions.vue +13 -9
- package/app/components/Viewer/Generic/Model/LinesOptions.vue +110 -61
- package/app/components/Viewer/Generic/Model/ModelStyleCard.vue +32 -21
- package/app/components/Viewer/Generic/Model/ModelStyleOptions.vue +9 -5
- package/app/components/Viewer/Generic/Model/PointsOptions.vue +19 -13
- package/app/components/Viewer/Generic/Model/SurfacesOptions.vue +119 -49
- package/app/components/Viewer/Grid/2D/CellsOptions.vue +8 -5
- package/app/components/Viewer/Grid/2D/EdgesOptions.vue +8 -5
- package/app/components/Viewer/Grid/2D/PointsOptions.vue +8 -5
- package/app/components/Viewer/Grid/3D/CellsOptions.vue +8 -5
- package/app/components/Viewer/Grid/3D/EdgesOptions.vue +8 -5
- package/app/components/Viewer/Grid/3D/FacetsOptions.vue +8 -5
- package/app/components/Viewer/Grid/3D/PointsOptions.vue +8 -5
- package/app/components/Viewer/ObjectTree/Base/CommonTreeView.vue +120 -76
- package/app/components/Viewer/ObjectTree/Base/Controls.vue +25 -10
- package/app/components/Viewer/ObjectTree/Base/ItemLabel.vue +42 -17
- package/app/components/Viewer/ObjectTree/Base/StickyHeader.vue +22 -9
- package/app/components/Viewer/ObjectTree/Base/TreeRow.vue +29 -14
- package/app/components/Viewer/ObjectTree/Box.vue +32 -15
- package/app/components/Viewer/ObjectTree/Layout.vue +55 -35
- package/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue +63 -34
- package/app/components/Viewer/ObjectTree/Views/{ModelCollections.vue → ModelTree.vue} +101 -39
- package/app/components/Viewer/Options/AttributeColorBar.vue +14 -6
- package/app/components/Viewer/Options/AttributeRangeSelector.vue +8 -4
- package/app/components/Viewer/Options/AttributeSelector.vue +64 -33
- package/app/components/Viewer/Options/ColorMapList.vue +52 -24
- package/app/components/Viewer/Options/ColorMapPicker.vue +15 -11
- package/app/components/Viewer/Options/ColorPicker.vue +239 -50
- package/app/components/Viewer/Options/ColoringTypeSelector.vue +87 -67
- package/app/components/Viewer/Options/ColormapQuickPicker.vue +16 -12
- package/app/components/Viewer/Options/OptionsSection.vue +7 -5
- package/app/components/Viewer/Options/Sliders/Size.vue +3 -3
- package/app/components/Viewer/Options/Sliders/Slider.vue +9 -6
- package/app/components/Viewer/Options/Sliders/Width.vue +3 -3
- package/app/components/Viewer/Options/TextureItem.vue +29 -22
- package/app/components/Viewer/Options/TexturesSelector.vue +23 -12
- package/app/components/Viewer/Options/VisibilitySwitch.vue +3 -3
- package/app/components/Viewer/OverlappingObjectsPicker.vue +27 -12
- package/app/components/Viewer/PointSet/SpecificPointsOptions.vue +38 -26
- package/app/components/Viewer/Solid/EdgesOptions.vue +8 -5
- package/app/components/Viewer/Solid/PointsOptions.vue +8 -5
- package/app/components/Viewer/Solid/PolygonsOptions.vue +8 -5
- package/app/components/Viewer/Solid/SpecificPolyhedraOptions.vue +73 -48
- package/app/components/Viewer/Surface/EdgesOptions.vue +8 -5
- package/app/components/Viewer/Surface/PointsOptions.vue +8 -5
- package/app/components/Viewer/Surface/PolygonsOptions.vue +79 -49
- package/app/components/Viewer/Surface/Triangulated/TrianglesOptions.vue +8 -5
- package/app/components/Viewer/TetrahedralSolid/TetrahedraOptions.vue +8 -5
- package/app/components/Viewer/TetrahedralSolid/TrianglesOptions.vue +8 -5
- package/app/components/Viewer/Ui.vue +19 -14
- package/app/components/Wrapper.vue +16 -10
- package/app/components/ZScaling.vue +18 -10
- package/app/components/csv-preview/CsvPreviewer.vue +72 -50
- package/app/components/csv-preview/CsvSettings.vue +30 -50
- package/app/components/csv-preview/CsvTable.vue +34 -14
- package/app/composables/{batch_style.js → batch_style.ts} +9 -7
- package/app/composables/clipping_planes_widget.ts +204 -0
- package/app/composables/clipping_planes_widget_entries.ts +189 -0
- package/app/composables/copy_to_clipboard.ts +7 -0
- package/app/composables/global_attribute_style.ts +303 -0
- package/app/composables/hover_highlight.ts +127 -0
- package/app/composables/{model_collections.js → model_collections.ts} +28 -9
- package/app/composables/{model_components.js → model_components.ts} +28 -9
- package/app/composables/{project_manager.js → project_manager.ts} +77 -20
- package/app/composables/responsive_middle_truncate.ts +48 -0
- package/app/composables/{run_function_when_microservices_connected.js → run_function_when_microservices_connected.ts} +1 -1
- package/app/composables/stepper_tree.ts +79 -0
- package/app/composables/tree_filter.ts +194 -0
- package/app/composables/{tree_keyboard_nav.js → tree_keyboard_nav.ts} +62 -20
- package/app/composables/{tree_scroll.js → tree_scroll.ts} +61 -12
- package/app/composables/use_adaptive_styles.ts +186 -0
- package/app/composables/use_overlapping_picker.ts +263 -0
- package/app/composables/use_quick_colormap.ts +55 -0
- package/app/composables/virtual_tree.ts +271 -0
- package/app/composables/vtk_implicit_plane_widget.d.ts +2 -0
- package/app/plugins/{auto_store_register.js → auto_store_register.ts} +3 -5
- package/app/plugins/click_outside_ignore_snackbars.client.ts +36 -0
- package/app/stores/app.ts +252 -0
- package/app/stores/app_helpers/extension.ts +179 -0
- package/app/stores/{back.js → back.ts} +54 -28
- package/app/stores/camera_manager.ts +80 -0
- package/app/stores/{cloud.js → cloud.ts} +18 -13
- package/app/stores/data.ts +392 -0
- package/app/stores/data_helpers/collections.ts +138 -0
- package/app/stores/data_helpers/mesh.ts +169 -0
- package/app/stores/data_style.ts +167 -0
- package/app/stores/{feedback.js → feedback.ts} +19 -8
- package/app/stores/{hybrid_viewer.js → hybrid_viewer.ts} +49 -45
- package/app/stores/infra.ts +106 -0
- package/app/stores/{menu.js → menu.ts} +67 -36
- package/app/stores/treeview.ts +383 -0
- package/app/stores/{viewer.js → viewer.ts} +75 -42
- package/app/utils/attributes.ts +40 -0
- package/app/utils/clipping_planes.ts +222 -0
- package/app/utils/color_picker.js +54 -0
- package/app/utils/colormap.ts +102 -0
- package/app/utils/default_styles/{constants.js → constants.ts} +25 -12
- package/app/utils/default_styles/{index.js → index.ts} +4 -3
- package/app/utils/default_styles/meshes.ts +264 -0
- package/app/utils/default_styles/{models.js → models.ts} +106 -52
- package/app/utils/{extension.js → extension.ts} +63 -19
- package/app/utils/{import_workflow.js → import_workflow.ts} +39 -22
- package/app/utils/{log.js → log.ts} +12 -2
- package/app/utils/{name_cleaner.js → name_cleaner.ts} +6 -6
- package/app/utils/status.ts +19 -0
- package/app/utils/{stores.js → stores.ts} +5 -5
- package/app/utils/{string.js → string.ts} +6 -6
- package/app/utils/{treeview.js → treeview.ts} +4 -1
- package/internal/database/{base_database.js → base_database.ts} +7 -3
- package/internal/database/database.ts +102 -0
- package/internal/database/{extended_database.js → extended_database.ts} +5 -1
- package/internal/database/tables/camera_positions.ts +6 -0
- package/internal/database/tables/{data.js → data.ts} +3 -1
- package/internal/database/tables/data_style.ts +6 -0
- package/internal/database/tables/model_component_datastyle.ts +6 -0
- package/internal/database/tables/model_component_type_datastyle.ts +6 -0
- package/internal/database/tables/model_components.ts +6 -0
- package/internal/database/tables/model_components_relation.ts +6 -0
- package/internal/database/tables/table_definition.ts +5 -0
- package/internal/stores/data_style/mesh/cells/cell.ts +279 -0
- package/internal/stores/data_style/mesh/cells/{color.js → color.ts} +13 -7
- package/internal/stores/data_style/mesh/cells/common.ts +50 -0
- package/internal/stores/data_style/mesh/cells/index.ts +161 -0
- package/internal/stores/data_style/mesh/cells/{textures.js → textures.ts} +14 -8
- package/internal/stores/data_style/mesh/cells/vertex.ts +285 -0
- package/internal/stores/data_style/mesh/cells/visibility.ts +46 -0
- package/internal/stores/data_style/mesh/edges/{color.js → color.ts} +13 -7
- package/internal/stores/data_style/mesh/edges/common.ts +41 -0
- package/internal/stores/data_style/mesh/edges/edge.ts +279 -0
- package/internal/stores/data_style/mesh/edges/index.ts +155 -0
- package/internal/stores/data_style/mesh/edges/vertex.ts +285 -0
- package/internal/stores/data_style/mesh/edges/visibility.ts +45 -0
- package/internal/stores/data_style/mesh/edges/width.ts +42 -0
- package/internal/stores/data_style/mesh/{index.js → index.ts} +34 -14
- package/internal/stores/data_style/mesh/points/{color.js → color.ts} +13 -7
- package/internal/stores/data_style/mesh/points/common.ts +51 -0
- package/internal/stores/data_style/mesh/points/index.ts +133 -0
- package/internal/stores/data_style/mesh/points/size.ts +43 -0
- package/internal/stores/data_style/mesh/points/vertex.ts +285 -0
- package/internal/stores/data_style/mesh/points/visibility.ts +49 -0
- package/internal/stores/data_style/mesh/polygons/{color.js → color.ts} +13 -7
- package/internal/stores/data_style/mesh/polygons/common.ts +50 -0
- package/internal/stores/data_style/mesh/polygons/index.ts +167 -0
- package/internal/stores/data_style/mesh/polygons/polygon.ts +282 -0
- package/internal/stores/data_style/mesh/polygons/{textures.js → textures.ts} +14 -8
- package/internal/stores/data_style/mesh/polygons/vertex.ts +288 -0
- package/internal/stores/data_style/mesh/polygons/visibility.ts +48 -0
- package/internal/stores/data_style/mesh/polyhedra/{color.js → color.ts} +13 -7
- package/internal/stores/data_style/mesh/polyhedra/common.ts +41 -0
- package/internal/stores/data_style/mesh/polyhedra/index.ts +157 -0
- package/internal/stores/data_style/mesh/polyhedra/polyhedron.ts +294 -0
- package/internal/stores/data_style/mesh/polyhedra/vertex.ts +288 -0
- package/internal/stores/data_style/mesh/polyhedra/visibility.ts +48 -0
- package/internal/stores/data_style/model/blocks/{color.js → color.ts} +50 -13
- package/internal/stores/data_style/model/blocks/common.ts +67 -0
- package/internal/stores/data_style/model/blocks/{index.js → index.ts} +111 -66
- package/internal/stores/data_style/model/blocks/polyhedron.ts +363 -0
- package/internal/stores/data_style/model/blocks/vertex.ts +349 -0
- package/internal/stores/data_style/model/blocks/visibility.ts +37 -0
- package/internal/stores/data_style/model/color.ts +348 -0
- package/internal/stores/data_style/model/common.ts +262 -0
- package/internal/stores/data_style/model/corners/{color.js → color.ts} +49 -10
- package/internal/stores/data_style/model/corners/common.ts +71 -0
- package/internal/stores/data_style/model/corners/{index.js → index.ts} +86 -47
- package/internal/stores/data_style/model/corners/vertex.ts +315 -0
- package/internal/stores/data_style/model/corners/visibility.ts +39 -0
- package/internal/stores/data_style/model/edges/common.ts +29 -0
- package/internal/stores/data_style/model/edges/{index.js → index.ts} +2 -7
- package/internal/stores/data_style/model/edges/visibility.ts +55 -0
- package/internal/stores/data_style/model/{index.js → index.ts} +24 -11
- package/internal/stores/data_style/model/lines/{color.js → color.ts} +47 -10
- package/internal/stores/data_style/model/lines/common.ts +63 -0
- package/internal/stores/data_style/model/lines/edge.ts +343 -0
- package/internal/stores/data_style/model/lines/{index.js → index.ts} +108 -66
- package/internal/stores/data_style/model/lines/vertex.ts +344 -0
- package/internal/stores/data_style/model/lines/visibility.ts +37 -0
- package/internal/stores/data_style/model/points/common.ts +25 -0
- package/internal/stores/data_style/model/points/index.ts +35 -0
- package/internal/stores/data_style/model/points/size.ts +44 -0
- package/internal/stores/data_style/model/points/visibility.ts +46 -0
- package/internal/stores/data_style/model/selection.ts +138 -0
- package/internal/stores/data_style/model/surfaces/{color.js → color.ts} +47 -10
- package/internal/stores/data_style/model/surfaces/common.ts +69 -0
- package/internal/stores/data_style/model/surfaces/{index.js → index.ts} +113 -66
- package/internal/stores/data_style/model/surfaces/polygon.ts +347 -0
- package/internal/stores/data_style/model/surfaces/vertex.ts +351 -0
- package/internal/stores/data_style/model/surfaces/visibility.ts +37 -0
- package/internal/stores/data_style/model/{visibility.js → visibility.ts} +112 -32
- package/internal/stores/data_style/state.ts +281 -0
- package/internal/stores/data_style/types.ts +30 -0
- package/internal/stores/hybrid_viewer/brightness.ts +124 -0
- package/internal/stores/hybrid_viewer/camera.ts +326 -0
- package/internal/stores/hybrid_viewer/{camera_animation.js → camera_animation.ts} +30 -12
- package/internal/stores/hybrid_viewer/{constants.js → constants.ts} +2 -2
- package/internal/stores/hybrid_viewer/core.ts +64 -0
- package/internal/stores/hybrid_viewer/{filters.js → filters.ts} +10 -13
- package/internal/stores/hybrid_viewer/highlight.ts +183 -0
- package/internal/stores/hybrid_viewer/{ruler.js → ruler.ts} +50 -22
- package/internal/stores/hybrid_viewer/scene.ts +125 -0
- package/internal/stores/hybrid_viewer/viewport.ts +177 -0
- package/internal/stores/hybrid_viewer/vtk_types.ts +58 -0
- package/internal/utils/api_fetch.ts +133 -0
- package/internal/utils/upload_file.ts +115 -0
- package/internal/utils/viewer_call.ts +99 -0
- package/internal/utils/ws_client.ts +54 -0
- package/nuxt.config.ts +168 -0
- package/opengeodeweb_front_schemas.json +2 -2
- package/package.json +49 -13
- package/server/api/cloud/extensions/{run.post.js → run.post.ts} +16 -12
- package/server/api/local/app/project_folder_path.post.ts +33 -0
- package/server/api/local/app/run_back.post.ts +39 -0
- package/server/api/local/app/run_viewer.post.ts +39 -0
- package/server/api/local/extensions/{kill.post.js → kill.post.ts} +15 -8
- package/server/api/local/extensions/{run.post.js → run.post.ts} +17 -12
- package/server/api/local/extensions/upload.put.ts +71 -0
- package/server/api/microservice/app/{get_is_app_ready.get.js → get_is_app_ready.get.ts} +5 -5
- package/server/api/microservice/app/schemas/get_is_app_ready.json +1 -1
- package/server/api/microservice/app/set_app_base_url.post.ts +29 -0
- package/server/api/microservice/app/set_back_base_url.post.ts +26 -0
- package/server/api/microservice/app/set_is_app_ready.post.ts +29 -0
- package/server/api/microservice/app/set_viewer_base_url.post.ts +26 -0
- package/server/api/microservice/extensions/{download.post.js → download.post.ts} +13 -6
- package/server/api/serverless/run_cloud.post.ts +92 -0
- package/server/utils/{app_config.js → app_config.ts} +40 -18
- package/server/utils/{cleanup.js → cleanup.ts} +76 -29
- package/server/utils/{cloud.js → cloud.ts} +33 -17
- package/server/utils/{extension.js → extension.ts} +31 -4
- package/server/utils/{microservices.js → microservices.ts} +68 -27
- package/server/utils/{path.js → path.ts} +36 -17
- package/server/utils/{scripts.js → scripts.ts} +49 -33
- package/server/utils/{server.js → server.ts} +13 -6
- package/server/utils/server_config.ts +74 -0
- package/server/utils/stream.ts +6 -0
- package/server/utils/ws_client.ts +165 -0
- package/shared/{scripts.js → scripts.ts} +15 -10
- package/shared/utils/call_raw.ts +73 -0
- package/shared/utils/{call_schema.js → call_schema.ts} +15 -6
- package/shared/utils/fetch_raw.ts +125 -0
- package/shared/utils/{fetch_schema.js → fetch_schema.ts} +16 -7
- package/shared/utils/file.ts +22 -0
- package/shared/utils/{parse_boolean.js → parse_boolean.ts} +1 -1
- package/shared/utils/response_handlers/load.ts +109 -0
- package/shared/utils/types.ts +27 -0
- package/shared/utils/{validate_schema.js → validate_schema.ts} +3 -1
- package/.github/workflows/config.json +0 -5
- package/.github/workflows/deploy.yml +0 -15
- package/.github/workflows/manual_release.yml +0 -11
- package/.github/workflows/merge_request.yml +0 -9
- package/.github/workflows/pr_update.yml +0 -11
- package/.github/workflows/prepare_deploy.yml +0 -9
- package/.github/workflows/schedule.yml +0 -18
- package/.github/workflows/test.yml +0 -14
- package/.github/workflows/test_pr.yml +0 -12
- package/.oxlintrc.json +0 -150
- package/.releaserc +0 -11
- package/app/components/Viewer/ObjectTree/Views/ModelComponents.vue +0 -224
- package/app/composables/clipping_planes_widget.js +0 -249
- package/app/composables/global_attribute_style.js +0 -181
- package/app/composables/hover_highlight.js +0 -91
- package/app/composables/responsive_middle_truncate.js +0 -34
- package/app/composables/stepper_tree.js +0 -56
- package/app/composables/tree_filter.js +0 -138
- package/app/composables/use_adaptive_styles.js +0 -120
- package/app/composables/use_overlapping_picker.js +0 -169
- package/app/composables/use_quick_colormap.js +0 -32
- package/app/composables/virtual_tree.js +0 -191
- package/app/stores/app.js +0 -326
- package/app/stores/camera_manager.js +0 -57
- package/app/stores/data.js +0 -278
- package/app/stores/data_helpers/collections.js +0 -96
- package/app/stores/data_helpers/mesh.js +0 -122
- package/app/stores/data_style.js +0 -116
- package/app/stores/infra.js +0 -95
- package/app/stores/treeview.js +0 -290
- package/app/utils/attributes.js +0 -23
- package/app/utils/clipping_planes.js +0 -110
- package/app/utils/colormap.js +0 -64
- package/app/utils/default_styles/meshes.js +0 -191
- package/app/utils/status.js +0 -10
- package/commitlint.config.js +0 -20
- package/internal/database/database.js +0 -80
- package/internal/database/tables/camera_positions.js +0 -4
- package/internal/database/tables/data_style.js +0 -4
- package/internal/database/tables/model_component_datastyle.js +0 -4
- package/internal/database/tables/model_component_type_datastyle.js +0 -4
- package/internal/database/tables/model_components.js +0 -4
- package/internal/database/tables/model_components_relation.js +0 -4
- package/internal/stores/data_style/mesh/cells/cell.js +0 -196
- package/internal/stores/data_style/mesh/cells/common.js +0 -39
- package/internal/stores/data_style/mesh/cells/index.js +0 -81
- package/internal/stores/data_style/mesh/cells/vertex.js +0 -193
- package/internal/stores/data_style/mesh/cells/visibility.js +0 -35
- package/internal/stores/data_style/mesh/edges/common.js +0 -32
- package/internal/stores/data_style/mesh/edges/edge.js +0 -195
- package/internal/stores/data_style/mesh/edges/index.js +0 -81
- package/internal/stores/data_style/mesh/edges/vertex.js +0 -196
- package/internal/stores/data_style/mesh/edges/visibility.js +0 -34
- package/internal/stores/data_style/mesh/edges/width.js +0 -34
- package/internal/stores/data_style/mesh/points/common.js +0 -37
- package/internal/stores/data_style/mesh/points/index.js +0 -82
- package/internal/stores/data_style/mesh/points/size.js +0 -35
- package/internal/stores/data_style/mesh/points/vertex.js +0 -193
- package/internal/stores/data_style/mesh/points/visibility.js +0 -37
- package/internal/stores/data_style/mesh/polygons/common.js +0 -32
- package/internal/stores/data_style/mesh/polygons/index.js +0 -107
- package/internal/stores/data_style/mesh/polygons/polygon.js +0 -196
- package/internal/stores/data_style/mesh/polygons/vertex.js +0 -196
- package/internal/stores/data_style/mesh/polygons/visibility.js +0 -38
- package/internal/stores/data_style/mesh/polyhedra/common.js +0 -32
- package/internal/stores/data_style/mesh/polyhedra/index.js +0 -98
- package/internal/stores/data_style/mesh/polyhedra/polyhedron.js +0 -196
- package/internal/stores/data_style/mesh/polyhedra/vertex.js +0 -196
- package/internal/stores/data_style/mesh/polyhedra/visibility.js +0 -38
- package/internal/stores/data_style/model/blocks/common.js +0 -51
- package/internal/stores/data_style/model/blocks/polyhedron.js +0 -215
- package/internal/stores/data_style/model/blocks/vertex.js +0 -204
- package/internal/stores/data_style/model/blocks/visibility.js +0 -20
- package/internal/stores/data_style/model/color.js +0 -218
- package/internal/stores/data_style/model/common.js +0 -141
- package/internal/stores/data_style/model/corners/common.js +0 -51
- package/internal/stores/data_style/model/corners/vertex.js +0 -204
- package/internal/stores/data_style/model/corners/visibility.js +0 -20
- package/internal/stores/data_style/model/edges/common.js +0 -20
- package/internal/stores/data_style/model/edges/visibility.js +0 -38
- package/internal/stores/data_style/model/lines/common.js +0 -51
- package/internal/stores/data_style/model/lines/edge.js +0 -203
- package/internal/stores/data_style/model/lines/vertex.js +0 -204
- package/internal/stores/data_style/model/lines/visibility.js +0 -20
- package/internal/stores/data_style/model/points/common.js +0 -20
- package/internal/stores/data_style/model/points/index.js +0 -25
- package/internal/stores/data_style/model/points/size.js +0 -36
- package/internal/stores/data_style/model/points/visibility.js +0 -36
- package/internal/stores/data_style/model/selection.js +0 -89
- package/internal/stores/data_style/model/surfaces/common.js +0 -51
- package/internal/stores/data_style/model/surfaces/polygon.js +0 -215
- package/internal/stores/data_style/model/surfaces/vertex.js +0 -215
- package/internal/stores/data_style/model/surfaces/visibility.js +0 -20
- package/internal/stores/data_style/state.js +0 -197
- package/internal/stores/hybrid_viewer/brightness.js +0 -82
- package/internal/stores/hybrid_viewer/camera.js +0 -274
- package/internal/stores/hybrid_viewer/highlight.js +0 -170
- package/internal/stores/hybrid_viewer/scene.js +0 -136
- package/internal/stores/hybrid_viewer/viewport.js +0 -140
- package/internal/utils/api_fetch.js +0 -52
- package/internal/utils/upload_file.js +0 -57
- package/internal/utils/viewer_call.js +0 -49
- package/internal/utils/ws_client.js +0 -29
- package/nuxt.config.js +0 -106
- package/scripts/generate_geode_objects.js +0 -24
- package/server/api/local/app/project_folder_path.post.js +0 -29
- package/server/api/local/app/run_back.post.js +0 -33
- package/server/api/local/app/run_viewer.post.js +0 -33
- package/server/api/local/extensions/upload.put.js +0 -72
- package/server/api/microservice/app/set_app_base_url.post.js +0 -25
- package/server/api/microservice/app/set_back_base_url.post.js +0 -22
- package/server/api/microservice/app/set_is_app_ready.post.js +0 -25
- package/server/api/microservice/app/set_viewer_base_url.post.js +0 -22
- package/server/api/serverless/run_cloud.post.js +0 -44
- package/server/utils/server_config.js +0 -58
- package/server/utils/ws_client.js +0 -112
- package/shared/utils/call_raw.js +0 -46
- package/shared/utils/fetch_raw.js +0 -61
- package/shared/utils/file.js +0 -16
- package/shared/utils/response_handlers/load.js +0 -74
- package/tests/integration/data/uploads/test.og_brep +0 -0
- package/tests/integration/data/uploads/test.og_edc2d +0 -0
- package/tests/integration/data/uploads/test.og_edc3d +0 -0
- package/tests/integration/data/uploads/test.og_psf3d +0 -0
- package/tests/integration/data/uploads/test.og_rgd2d +0 -0
- package/tests/integration/data/uploads/test.og_rgd3d +0 -0
- package/tests/integration/data/uploads/test.vtu +0 -22
- package/tests/integration/setup.js +0 -92
- package/tests/integration/stores/data_style/mesh/cells.nuxt.test.js +0 -343
- package/tests/integration/stores/data_style/mesh/edges.nuxt.test.js +0 -254
- package/tests/integration/stores/data_style/mesh/index.nuxt.test.js +0 -62
- package/tests/integration/stores/data_style/mesh/points.nuxt.test.js +0 -201
- package/tests/integration/stores/data_style/mesh/polygons.nuxt.test.js +0 -260
- package/tests/integration/stores/data_style/mesh/polyhedra.nuxt.test.js +0 -267
- package/tests/integration/stores/data_style/model/blocks.nuxt.test.js +0 -397
- package/tests/integration/stores/data_style/model/corners.nuxt.test.js +0 -264
- package/tests/integration/stores/data_style/model/edges.nuxt.test.js +0 -71
- package/tests/integration/stores/data_style/model/index.nuxt.test.js +0 -92
- package/tests/integration/stores/data_style/model/lines.nuxt.test.js +0 -379
- package/tests/integration/stores/data_style/model/points.nuxt.test.js +0 -95
- package/tests/integration/stores/data_style/model/surfaces.nuxt.test.js +0 -574
- package/tests/integration/stores/viewer.nuxt.test.js +0 -69
- package/tests/setup_indexeddb.js +0 -4
- package/tests/unit/components/CrsSelector.nuxt.test.js +0 -55
- package/tests/unit/components/DragAndDrop.nuxt.test.js +0 -89
- package/tests/unit/components/ExtensionSelector.nuxt.test.js +0 -65
- package/tests/unit/components/FeedBack/ErrorsBanner.nuxt.test.js +0 -41
- package/tests/unit/components/FeedBack/Snackers.nuxt.test.js +0 -49
- package/tests/unit/components/FileSelector.nuxt.test.js +0 -124
- package/tests/unit/components/FileUploader.nuxt.test.js +0 -69
- package/tests/unit/components/MissingFilesSelector.nuxt.test.js +0 -77
- package/tests/unit/components/ObjectSelector.nuxt.test.js +0 -118
- package/tests/unit/components/PackagesVersions.nuxt.test.js +0 -42
- package/tests/unit/components/Step.nuxt.test.js +0 -51
- package/tests/unit/components/Stepper.nuxt.test.js +0 -41
- package/tests/unit/components/ToolPanel.nuxt.test.js +0 -66
- package/tests/unit/composables/api_fetch.nuxt.test.js +0 -75
- package/tests/unit/composables/project_manager.nuxt.test.js +0 -299
- package/tests/unit/composables/run_function_when_microservices_connected.nuxt.test.js +0 -57
- package/tests/unit/composables/upload_file.nuxt.test.js +0 -45
- package/tests/unit/composables/virtual_tree.nuxt.test.js +0 -63
- package/tests/unit/plugins/project_load.nuxt.test.js +0 -98
- package/tests/unit/stores/app.nuxt.test.js +0 -189
- package/tests/unit/stores/back.nuxt.test.js +0 -147
- package/tests/unit/stores/cloud.nuxt.test.js +0 -90
- package/tests/unit/stores/data.nuxt.test.js +0 -162
- package/tests/unit/stores/feedback.nuxt.test.js +0 -90
- package/tests/unit/stores/infra.nuxt.test.js +0 -313
- package/tests/unit/stores/treeview.nuxt.test.js +0 -63
- package/tests/unit/stores/viewer.nuxt.test.js +0 -161
- package/tests/unit/utils/validate_schema.nuxt.test.js +0 -38
- package/tests/utils.js +0 -20
- package/tests/vitest.config.js +0 -67
- /package/server/api/local/app/{kill.post.js → kill.post.ts} +0 -0
- /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.
|
|
11
|
+
} from "@geode/opengeodeweb-front/server/utils/app_config.ts";
|
|
12
12
|
|
|
13
|
-
|
|
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
|
|
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
|
-
|
|
13
|
-
|
|
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
|
-
|
|
25
|
+
|
|
26
|
+
function confFolderPath(projectName: string): string {
|
|
22
27
|
const projectConfig = projectConf(projectName);
|
|
23
28
|
return path.dirname(projectConfig.path);
|
|
24
29
|
}
|
|
25
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
52
|
-
|
|
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
|
-
|
|
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
|
|
69
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
74
|
+
await pTimeout(do_kill(), {
|
|
53
75
|
milliseconds: 5000,
|
|
54
76
|
message: failMessage,
|
|
55
77
|
});
|
|
56
78
|
}
|
|
57
|
-
|
|
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
|
-
|
|
66
|
-
const socket = new WebSocket(
|
|
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
|
-
|
|
134
|
+
await pTimeout(do_kill(), {
|
|
108
135
|
milliseconds: 5000,
|
|
109
136
|
message: failMessage,
|
|
110
137
|
});
|
|
111
138
|
}
|
|
112
|
-
|
|
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
|
-
|
|
146
|
+
const exhaustiveCheck: never = microservice.type;
|
|
147
|
+
throw new Error(`Unknown microservice type: ${String(exhaustiveCheck)}`);
|
|
119
148
|
}
|
|
120
149
|
}
|
|
121
|
-
|
|
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) =>
|
|
156
|
+
microservices.map(async (microservice) => {
|
|
157
|
+
await killMicroservice(microservice);
|
|
158
|
+
}),
|
|
127
159
|
);
|
|
128
|
-
|
|
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
|
-
|
|
162
|
+
|
|
163
|
+
function microservicesMetadatasPath(projectFolderPath: string): string {
|
|
135
164
|
return path.join(projectFolderPath, "microservices.json");
|
|
136
165
|
}
|
|
137
166
|
|
|
138
|
-
function
|
|
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
|
|
150
|
-
|
|
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
|
-
|
|
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
|
-
|
|
162
|
-
|
|
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
|
-
|
|
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 [
|
|
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
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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 =
|
|
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.
|
|
10
|
+
import { extensionFrontendPath } from "@geode/opengeodeweb-front/server/utils/path.ts";
|
|
10
11
|
|
|
11
|
-
|
|
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
|
-
|
|
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(
|
|
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,
|