@geode/opengeodeweb-front 10.34.0-rc.8 → 10.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{server → .build/server}/utils/app_config.js +10 -9
- package/{server → .build/server}/utils/cleanup.js +31 -17
- package/{server → .build/server}/utils/cloud.js +1 -4
- package/{server → .build/server}/utils/microservices.js +21 -9
- package/{server → .build/server}/utils/path.js +4 -4
- package/{server → .build/server}/utils/scripts.js +9 -9
- package/.build/server/utils/server_config.js +51 -0
- package/.build/server/utils/stream.js +6 -0
- package/{server → .build/server}/utils/ws_client.js +18 -3
- package/{shared → .build/shared}/scripts.js +10 -10
- package/.build/shared/utils/call_raw.js +31 -0
- package/{shared → .build/shared}/utils/call_schema.js +2 -2
- package/.build/shared/utils/fetch_raw.js +52 -0
- package/{shared → .build/shared}/utils/fetch_schema.js +2 -2
- package/{shared → .build/shared}/utils/file.js +3 -1
- package/{shared → .build/shared}/utils/response_handlers/load.js +10 -7
- package/{shared → .build/shared}/utils/validate_schema.js +1 -1
- package/app/components/ActionButton.vue +6 -6
- package/app/components/CameraManager/List.vue +5 -5
- package/app/components/CameraManager/Saver.vue +3 -5
- package/app/components/CameraManager.vue +6 -4
- package/app/components/CameraOrientation.vue +12 -12
- package/app/components/ClippingPlaneCard.vue +4 -2
- package/app/components/ClippingPlanes.vue +8 -8
- package/app/components/CrsSelector.vue +9 -10
- package/app/components/DeleteDialog.vue +4 -2
- package/app/components/DragAndDrop.vue +10 -12
- package/app/components/DragAndDropInternal/DragAndDropInline.vue +4 -2
- package/app/components/ExtensionSelector.vue +4 -4
- package/app/components/FeedBack/ErrorBanner.vue +3 -1
- package/app/components/FeedBack/Snackers.vue +4 -3
- package/app/components/FileSelector.vue +10 -8
- package/app/components/FileUploader.vue +11 -11
- package/app/components/GlassCard.vue +1 -1
- package/app/components/HybridRenderingView.vue +7 -5
- package/app/components/HybridViewerTooltip.vue +7 -7
- package/app/components/Launcher.vue +1 -1
- package/app/components/Loading/EcoMessages.vue +9 -3
- package/app/components/Loading.vue +2 -2
- package/app/components/MissingFilesSelector.vue +12 -10
- package/app/components/ObjectSelector.vue +10 -9
- package/app/components/PackagesVersions.vue +6 -5
- package/app/components/Recaptcha.vue +3 -3
- package/app/components/RemoteRenderingView.vue +6 -7
- package/app/components/Ruler.vue +3 -3
- package/app/components/Screenshot.vue +6 -6
- package/app/components/SearchBar.vue +4 -2
- package/app/components/ShrinkFilter.vue +7 -7
- package/app/components/Step.vue +6 -5
- package/app/components/Stepper.vue +4 -3
- package/app/components/ToolPanel.vue +6 -3
- package/app/components/ViewToolbar.vue +25 -28
- package/app/components/Viewer/ContextMenu/CenterButton.vue +7 -5
- package/app/components/Viewer/ContextMenu/CircularItems.vue +3 -3
- package/app/components/Viewer/ContextMenu/ContextMenu.vue +22 -19
- package/app/components/Viewer/ContextMenu/ContextMenuItem.vue +10 -8
- package/app/components/Viewer/ContextMenu/InfoCard.vue +11 -12
- package/app/components/Viewer/EdgedCurve/SpecificEdgesOptions.vue +13 -17
- package/app/components/Viewer/Generic/Mesh/CellsOptions.vue +11 -15
- package/app/components/Viewer/Generic/Mesh/EdgesOptions.vue +12 -16
- package/app/components/Viewer/Generic/Mesh/PointsOptions.vue +8 -12
- package/app/components/Viewer/Generic/Mesh/PolygonsOptions.vue +11 -15
- package/app/components/Viewer/Generic/Mesh/PolyhedraOptions.vue +11 -15
- package/app/components/Viewer/Generic/Model/BlocksOptions.vue +67 -38
- package/app/components/Viewer/Generic/Model/CornersOptions.vue +53 -23
- package/app/components/Viewer/Generic/Model/EdgesOptions.vue +1 -3
- package/app/components/Viewer/Generic/Model/LinesOptions.vue +67 -38
- package/app/components/Viewer/Generic/Model/ModelStyleCard.vue +31 -15
- package/app/components/Viewer/Generic/Model/ModelStyleOptions.vue +2 -3
- package/app/components/Viewer/Generic/Model/PointsOptions.vue +6 -6
- package/app/components/Viewer/Generic/Model/SurfacesOptions.vue +69 -38
- package/app/components/Viewer/ObjectTree/Base/CommonTreeView.vue +64 -46
- package/app/components/Viewer/ObjectTree/Base/Controls.vue +5 -5
- package/app/components/Viewer/ObjectTree/Base/ItemLabel.vue +13 -9
- package/app/components/Viewer/ObjectTree/Base/StickyHeader.vue +5 -5
- package/app/components/Viewer/ObjectTree/Base/TreeRow.vue +10 -10
- package/app/components/Viewer/ObjectTree/Box.vue +6 -4
- package/app/components/Viewer/ObjectTree/Layout.vue +23 -21
- package/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue +14 -14
- package/app/components/Viewer/ObjectTree/Views/{ModelCollections.vue → ModelTree.vue} +59 -24
- package/app/components/Viewer/Options/AttributeColorBar.vue +4 -2
- package/app/components/Viewer/Options/AttributeRangeSelector.vue +4 -2
- package/app/components/Viewer/Options/AttributeSelector.vue +7 -9
- package/app/components/Viewer/Options/ColorMapList.vue +15 -13
- package/app/components/Viewer/Options/ColorMapPicker.vue +4 -4
- package/app/components/Viewer/Options/ColorPicker.vue +223 -41
- package/app/components/Viewer/Options/ColoringTypeSelector.vue +16 -16
- package/app/components/Viewer/Options/ColormapQuickPicker.vue +7 -5
- package/app/components/Viewer/Options/OptionsSection.vue +1 -1
- package/app/components/Viewer/Options/TextureItem.vue +8 -6
- package/app/components/Viewer/Options/TexturesSelector.vue +1 -1
- package/app/components/Viewer/OverlappingObjectsPicker.vue +8 -9
- package/app/components/Viewer/PointSet/SpecificPointsOptions.vue +2 -6
- package/app/components/Viewer/Solid/SpecificPolyhedraOptions.vue +12 -16
- package/app/components/Viewer/Surface/PolygonsOptions.vue +12 -16
- package/app/components/Viewer/Ui.vue +2 -2
- package/app/components/Wrapper.vue +1 -4
- package/app/components/ZScaling.vue +5 -3
- package/app/components/csv-preview/CsvPreviewer.vue +38 -37
- package/app/components/csv-preview/CsvSettings.vue +6 -4
- package/app/components/csv-preview/CsvTable.vue +1 -1
- package/app/composables/batch_style.ts +5 -6
- package/app/composables/clipping_planes_widget.ts +73 -181
- 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 +163 -83
- package/app/composables/hover_highlight.ts +46 -14
- package/app/composables/model_collections.ts +26 -13
- package/app/composables/model_components.ts +26 -13
- package/app/composables/project_manager.ts +76 -19
- package/app/composables/responsive_middle_truncate.ts +13 -13
- package/app/composables/stepper_tree.ts +34 -11
- package/app/composables/tree_filter.ts +66 -44
- package/app/composables/tree_keyboard_nav.ts +25 -11
- package/app/composables/tree_scroll.ts +44 -14
- package/app/composables/use_adaptive_styles.ts +66 -23
- package/app/composables/use_overlapping_picker.ts +66 -16
- package/app/composables/use_quick_colormap.ts +16 -5
- package/app/composables/virtual_tree.ts +75 -43
- package/app/composables/vtk_implicit_plane_widget.d.ts +2 -0
- package/app/plugins/auto_store_register.ts +2 -7
- package/app/plugins/click_outside_ignore_snackbars.client.ts +39 -0
- package/app/stores/app.ts +57 -192
- package/app/stores/app_helpers/extension.ts +179 -0
- package/app/stores/back.ts +37 -21
- package/app/stores/camera_manager.ts +22 -20
- package/app/stores/cloud.ts +17 -13
- package/app/stores/data.ts +88 -47
- package/app/stores/data_helpers/collections.ts +36 -38
- package/app/stores/data_helpers/mesh.ts +45 -36
- package/app/stores/data_style.ts +50 -28
- package/app/stores/feedback.ts +6 -6
- package/app/stores/hybrid_viewer.ts +41 -52
- package/app/stores/infra.ts +39 -37
- package/app/stores/menu.ts +23 -14
- package/app/stores/treeview.ts +72 -42
- package/app/stores/viewer.ts +39 -27
- package/app/utils/attributes.ts +3 -3
- package/app/utils/clipping_planes.ts +111 -14
- package/app/utils/color_picker.ts +57 -0
- package/app/utils/colormap.ts +58 -35
- package/app/utils/default_styles/index.ts +2 -2
- package/app/utils/default_styles/meshes.ts +107 -13
- package/app/utils/default_styles/models.ts +83 -14
- package/app/utils/extension.ts +47 -20
- package/app/utils/import_workflow.ts +21 -13
- package/app/utils/name_cleaner.ts +1 -1
- package/app/utils/string.ts +1 -1
- package/app/utils/treeview.ts +2 -2
- package/internal/database/base_database.ts +7 -3
- package/internal/database/database.ts +36 -26
- package/internal/database/extended_database.ts +1 -1
- package/internal/stores/data_style/mesh/cells/cell.ts +70 -34
- package/internal/stores/data_style/mesh/cells/color.ts +12 -6
- package/internal/stores/data_style/mesh/cells/common.ts +18 -8
- package/internal/stores/data_style/mesh/cells/index.ts +122 -42
- package/internal/stores/data_style/mesh/cells/textures.ts +12 -6
- package/internal/stores/data_style/mesh/cells/vertex.ts +75 -34
- package/internal/stores/data_style/mesh/cells/visibility.ts +15 -4
- package/internal/stores/data_style/mesh/edges/color.ts +12 -6
- package/internal/stores/data_style/mesh/edges/common.ts +14 -6
- package/internal/stores/data_style/mesh/edges/edge.ts +71 -39
- package/internal/stores/data_style/mesh/edges/index.ts +117 -42
- package/internal/stores/data_style/mesh/edges/vertex.ts +76 -39
- package/internal/stores/data_style/mesh/edges/visibility.ts +15 -4
- package/internal/stores/data_style/mesh/edges/width.ts +12 -4
- package/internal/stores/data_style/mesh/index.ts +30 -11
- package/internal/stores/data_style/mesh/points/color.ts +12 -6
- package/internal/stores/data_style/mesh/points/common.ts +21 -8
- package/internal/stores/data_style/mesh/points/index.ts +101 -50
- package/internal/stores/data_style/mesh/points/size.ts +12 -4
- package/internal/stores/data_style/mesh/points/vertex.ts +75 -34
- package/internal/stores/data_style/mesh/points/visibility.ts +17 -7
- package/internal/stores/data_style/mesh/polygons/color.ts +12 -6
- package/internal/stores/data_style/mesh/polygons/common.ts +23 -6
- package/internal/stores/data_style/mesh/polygons/index.ts +130 -70
- package/internal/stores/data_style/mesh/polygons/polygon.ts +77 -43
- package/internal/stores/data_style/mesh/polygons/textures.ts +12 -6
- package/internal/stores/data_style/mesh/polygons/vertex.ts +79 -39
- package/internal/stores/data_style/mesh/polygons/visibility.ts +16 -6
- package/internal/stores/data_style/mesh/polyhedra/color.ts +12 -6
- package/internal/stores/data_style/mesh/polyhedra/common.ts +14 -6
- package/internal/stores/data_style/mesh/polyhedra/index.ts +115 -56
- package/internal/stores/data_style/mesh/polyhedra/polyhedron.ts +80 -39
- package/internal/stores/data_style/mesh/polyhedra/vertex.ts +79 -39
- package/internal/stores/data_style/mesh/polyhedra/visibility.ts +16 -6
- package/internal/stores/data_style/model/blocks/color.ts +43 -13
- package/internal/stores/data_style/model/blocks/common.ts +21 -6
- package/internal/stores/data_style/model/blocks/index.ts +89 -59
- package/internal/stores/data_style/model/blocks/polyhedron.ts +101 -44
- package/internal/stores/data_style/model/blocks/vertex.ts +107 -42
- package/internal/stores/data_style/model/blocks/visibility.ts +17 -4
- package/internal/stores/data_style/model/color.ts +171 -83
- package/internal/stores/data_style/model/common.ts +70 -21
- package/internal/stores/data_style/model/corners/color.ts +43 -11
- package/internal/stores/data_style/model/corners/common.ts +25 -6
- package/internal/stores/data_style/model/corners/index.ts +66 -41
- package/internal/stores/data_style/model/corners/vertex.ts +105 -74
- package/internal/stores/data_style/model/corners/visibility.ts +19 -4
- package/internal/stores/data_style/model/edges/common.ts +12 -4
- package/internal/stores/data_style/model/edges/index.ts +2 -1
- package/internal/stores/data_style/model/edges/visibility.ts +24 -7
- package/internal/stores/data_style/model/index.ts +24 -11
- package/internal/stores/data_style/model/lines/color.ts +41 -11
- package/internal/stores/data_style/model/lines/common.ts +17 -6
- package/internal/stores/data_style/model/lines/edge.ts +105 -42
- package/internal/stores/data_style/model/lines/index.ts +86 -59
- package/internal/stores/data_style/model/lines/vertex.ts +105 -42
- package/internal/stores/data_style/model/lines/visibility.ts +17 -4
- package/internal/stores/data_style/model/points/common.ts +8 -4
- package/internal/stores/data_style/model/points/index.ts +10 -3
- package/internal/stores/data_style/model/points/size.ts +12 -4
- package/internal/stores/data_style/model/points/visibility.ts +16 -6
- package/internal/stores/data_style/model/selection.ts +80 -58
- package/internal/stores/data_style/model/surfaces/color.ts +41 -11
- package/internal/stores/data_style/model/surfaces/common.ts +23 -6
- package/internal/stores/data_style/model/surfaces/index.ts +89 -59
- package/internal/stores/data_style/model/surfaces/polygon.ts +107 -67
- package/internal/stores/data_style/model/surfaces/vertex.ts +111 -67
- package/internal/stores/data_style/model/surfaces/visibility.ts +18 -5
- package/internal/stores/data_style/model/visibility.ts +82 -20
- package/internal/stores/data_style/state.ts +77 -65
- package/internal/stores/hybrid_viewer/brightness.ts +49 -31
- package/internal/stores/hybrid_viewer/camera.ts +191 -177
- package/internal/stores/hybrid_viewer/camera_animation.ts +11 -10
- package/internal/stores/hybrid_viewer/core.ts +64 -0
- package/internal/stores/hybrid_viewer/filters.ts +10 -16
- package/internal/stores/hybrid_viewer/highlight.ts +91 -130
- package/internal/stores/hybrid_viewer/ruler.ts +24 -15
- package/internal/stores/hybrid_viewer/scene.ts +96 -117
- package/internal/stores/hybrid_viewer/viewport.ts +74 -65
- package/internal/stores/hybrid_viewer/vtk_types.ts +13 -29
- package/internal/utils/api_fetch.ts +54 -23
- package/internal/utils/upload_file.ts +74 -53
- package/internal/utils/viewer_call.ts +22 -13
- package/internal/utils/ws_client.ts +24 -13
- package/nuxt.config.ts +58 -1
- package/package.json +20 -8
- package/server/api/cloud/extensions/run.post.ts +6 -10
- package/server/api/local/app/project_folder_path.post.ts +4 -4
- package/server/api/local/app/run_back.post.ts +5 -7
- package/server/api/local/app/run_viewer.post.ts +5 -7
- package/server/api/local/extensions/kill.post.ts +4 -3
- package/server/api/local/extensions/run.post.ts +7 -10
- package/server/api/local/extensions/upload.put.ts +44 -54
- package/server/api/microservice/app/get_is_app_ready.get.ts +4 -5
- package/server/api/microservice/app/set_app_base_url.post.ts +5 -6
- package/server/api/microservice/app/set_back_base_url.post.ts +5 -6
- package/server/api/microservice/app/set_is_app_ready.post.ts +5 -6
- package/server/api/microservice/app/set_viewer_base_url.post.ts +5 -6
- package/server/api/microservice/extensions/download.post.ts +5 -4
- package/server/api/serverless/run_cloud.post.ts +53 -11
- package/server/utils/app_config.ts +29 -22
- package/server/utils/cleanup.ts +60 -30
- package/server/utils/cloud.ts +9 -8
- package/server/utils/extension.ts +23 -9
- package/server/utils/microservices.ts +33 -24
- package/server/utils/path.ts +4 -4
- package/server/utils/scripts.ts +26 -23
- package/server/utils/server.ts +2 -2
- package/server/utils/server_config.ts +41 -27
- package/server/utils/stream.ts +6 -0
- package/server/utils/ws_client.ts +42 -8
- package/shared/scripts.ts +15 -10
- package/shared/utils/call_raw.ts +23 -16
- package/shared/utils/call_schema.ts +5 -8
- package/shared/utils/fetch_raw.ts +87 -47
- package/shared/utils/fetch_schema.ts +6 -9
- package/shared/utils/file.ts +8 -2
- package/shared/utils/response_handlers/load.ts +26 -11
- package/shared/utils/types.ts +9 -9
- package/shared/utils/validate_schema.ts +1 -1
- package/app/components/Viewer/ObjectTree/Views/ModelComponents.vue +0 -276
- package/server/types/vendor.d.ts +0 -64
- package/server/utils/server_config.js +0 -43
- package/shared/utils/call_raw.js +0 -30
- package/shared/utils/fetch_raw.js +0 -40
- /package/{opengeodeweb_front_schemas.js → .build/opengeodeweb_front_schemas.js} +0 -0
- /package/{server → .build/server}/utils/server.js +0 -0
- /package/{shared → .build/shared}/app_mode.js +0 -0
- /package/{shared → .build/shared}/utils/parse_boolean.js +0 -0
- /package/{shared → .build/shared}/utils/types.js +0 -0
|
@@ -4,17 +4,16 @@ import { createError, defineEventHandler } from "h3";
|
|
|
4
4
|
// Local imports
|
|
5
5
|
import { getIsAppReady } from "@geode/opengeodeweb-front/server/utils/server_config.ts";
|
|
6
6
|
|
|
7
|
-
export default defineEventHandler(
|
|
7
|
+
export default defineEventHandler(() => {
|
|
8
8
|
try {
|
|
9
|
-
const isReady =
|
|
9
|
+
const isReady = getIsAppReady();
|
|
10
10
|
console.log(`IS_APP_READY is ${isReady}`);
|
|
11
11
|
return { statusCode: 200, isReady };
|
|
12
12
|
} catch (error) {
|
|
13
13
|
console.log(error);
|
|
14
|
-
const err = error as { statusCode?: number; statusMessage?: string; message?: string };
|
|
15
14
|
throw createError({
|
|
16
|
-
statusCode:
|
|
17
|
-
statusMessage:
|
|
15
|
+
statusCode: 500,
|
|
16
|
+
statusMessage: error instanceof Error ? error.message : String(error),
|
|
18
17
|
});
|
|
19
18
|
}
|
|
20
19
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Third party imports
|
|
2
|
-
import { createError, defineEventHandler, readBody } from "h3";
|
|
2
|
+
import { type H3Event, createError, defineEventHandler, readBody } from "h3";
|
|
3
3
|
|
|
4
4
|
// Local imports
|
|
5
5
|
import { setAppBaseUrl } from "@geode/opengeodeweb-front/server/utils/server_config.ts";
|
|
@@ -8,23 +8,22 @@ interface SetAppBaseUrlBody {
|
|
|
8
8
|
baseUrl: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export default defineEventHandler(async (event) => {
|
|
11
|
+
export default defineEventHandler(async (event: H3Event) => {
|
|
12
12
|
try {
|
|
13
13
|
const { baseUrl } = await readBody<SetAppBaseUrlBody>(event);
|
|
14
14
|
if (!baseUrl) {
|
|
15
15
|
throw createError({ statusCode: 400, statusMessage: "baseUrl is required" });
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
setAppBaseUrl(baseUrl);
|
|
19
19
|
console.log(`Updated APP_BASE_URL to ${baseUrl}`);
|
|
20
20
|
|
|
21
21
|
return { statusCode: 200, baseUrl };
|
|
22
22
|
} catch (error) {
|
|
23
23
|
console.log(error);
|
|
24
|
-
const err = error as { statusCode?: number; statusMessage?: string; message?: string };
|
|
25
24
|
throw createError({
|
|
26
|
-
statusCode:
|
|
27
|
-
statusMessage:
|
|
25
|
+
statusCode: 500,
|
|
26
|
+
statusMessage: error instanceof Error ? error.message : String(error),
|
|
28
27
|
});
|
|
29
28
|
}
|
|
30
29
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Third party imports
|
|
2
|
-
import { createError, defineEventHandler, readBody } from "h3";
|
|
2
|
+
import { type H3Event, createError, defineEventHandler, readBody } from "h3";
|
|
3
3
|
|
|
4
4
|
// Local imports
|
|
5
5
|
import { setBackBaseUrl } from "@geode/opengeodeweb-front/server/utils/server_config.ts";
|
|
@@ -8,20 +8,19 @@ interface SetBackBaseUrlBody {
|
|
|
8
8
|
baseUrl: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export default defineEventHandler(async (event) => {
|
|
11
|
+
export default defineEventHandler(async (event: H3Event) => {
|
|
12
12
|
try {
|
|
13
13
|
const { baseUrl } = await readBody<SetBackBaseUrlBody>(event);
|
|
14
14
|
if (!baseUrl) {
|
|
15
15
|
throw createError({ statusCode: 400, statusMessage: "baseUrl is required" });
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
setBackBaseUrl(baseUrl);
|
|
18
18
|
return { statusCode: 200, baseUrl };
|
|
19
19
|
} catch (error) {
|
|
20
20
|
console.log(error);
|
|
21
|
-
const err = error as { statusCode?: number; message?: string };
|
|
22
21
|
throw createError({
|
|
23
|
-
statusCode:
|
|
24
|
-
statusMessage:
|
|
22
|
+
statusCode: 500,
|
|
23
|
+
statusMessage: error instanceof Error ? error.message : String(error),
|
|
25
24
|
});
|
|
26
25
|
}
|
|
27
26
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Third party imports
|
|
2
|
-
import { createError, defineEventHandler, readBody } from "h3";
|
|
2
|
+
import { type H3Event, createError, defineEventHandler, readBody } from "h3";
|
|
3
3
|
|
|
4
4
|
// Local imports
|
|
5
5
|
import { setIsAppReady } from "@geode/opengeodeweb-front/server/utils/server_config.ts";
|
|
@@ -8,23 +8,22 @@ interface SetIsAppReadyBody {
|
|
|
8
8
|
isReady: boolean;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export default defineEventHandler(async (event) => {
|
|
11
|
+
export default defineEventHandler(async (event: H3Event) => {
|
|
12
12
|
try {
|
|
13
13
|
const { isReady } = await readBody<SetIsAppReadyBody>(event);
|
|
14
14
|
if (!isReady) {
|
|
15
15
|
throw createError({ statusCode: 400, statusMessage: "isReady is required" });
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
setIsAppReady(isReady);
|
|
19
19
|
console.log(`Updated IS_APP_READY to ${isReady}`);
|
|
20
20
|
|
|
21
21
|
return { statusCode: 200, isReady };
|
|
22
22
|
} catch (error) {
|
|
23
23
|
console.log(error);
|
|
24
|
-
const err = error as { statusCode?: number; statusMessage?: string; message?: string };
|
|
25
24
|
throw createError({
|
|
26
|
-
statusCode:
|
|
27
|
-
statusMessage:
|
|
25
|
+
statusCode: 500,
|
|
26
|
+
statusMessage: error instanceof Error ? error.message : String(error),
|
|
28
27
|
});
|
|
29
28
|
}
|
|
30
29
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Third party imports
|
|
2
|
-
import { createError, defineEventHandler, readBody } from "h3";
|
|
2
|
+
import { type H3Event, createError, defineEventHandler, readBody } from "h3";
|
|
3
3
|
|
|
4
4
|
// Local imports
|
|
5
5
|
import { setViewerBaseUrl } from "@geode/opengeodeweb-front/server/utils/server_config.ts";
|
|
@@ -8,20 +8,19 @@ interface SetViewerBaseUrlBody {
|
|
|
8
8
|
baseUrl: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export default defineEventHandler(async (event) => {
|
|
11
|
+
export default defineEventHandler(async (event: H3Event) => {
|
|
12
12
|
try {
|
|
13
13
|
const { baseUrl } = await readBody<SetViewerBaseUrlBody>(event);
|
|
14
14
|
if (!baseUrl) {
|
|
15
15
|
throw createError({ statusCode: 400, statusMessage: "baseUrl is required" });
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
setViewerBaseUrl(baseUrl);
|
|
18
18
|
return { statusCode: 200, baseUrl };
|
|
19
19
|
} catch (error) {
|
|
20
20
|
console.log(error);
|
|
21
|
-
const err = error as { statusCode?: number; message?: string };
|
|
22
21
|
throw createError({
|
|
23
|
-
statusCode:
|
|
24
|
-
statusMessage:
|
|
22
|
+
statusCode: 500,
|
|
23
|
+
statusMessage: error instanceof Error ? error.message : String(error),
|
|
25
24
|
});
|
|
26
25
|
}
|
|
27
26
|
});
|
|
@@ -2,7 +2,7 @@
|
|
|
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 {
|
|
@@ -16,12 +16,13 @@ interface DownloadExtensionBody {
|
|
|
16
16
|
extensionFileName: string;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export default defineEventHandler(async (event) => {
|
|
19
|
+
export default defineEventHandler(async (event: H3Event) => {
|
|
20
20
|
try {
|
|
21
21
|
const body = await readBody<DownloadExtensionBody>(event);
|
|
22
22
|
const { projectName, url, extensionFileName } = body;
|
|
23
23
|
console.log({ projectName, url, extensionFileName });
|
|
24
|
-
const
|
|
24
|
+
const response: Response = await fetch(url);
|
|
25
|
+
const fileBuffer = await response.arrayBuffer();
|
|
25
26
|
const filePath = targetExtensionFilePath(projectName, extensionFileName);
|
|
26
27
|
await fs.writeFile(filePath, Buffer.from(fileBuffer));
|
|
27
28
|
await registerExtensionFile(projectName, filePath);
|
|
@@ -32,7 +33,7 @@ export default defineEventHandler(async (event) => {
|
|
|
32
33
|
console.error("Error downloading extension:", error);
|
|
33
34
|
throw createError({
|
|
34
35
|
statusCode: 500,
|
|
35
|
-
statusMessage:
|
|
36
|
+
statusMessage: error instanceof Error ? error.message : String(error),
|
|
36
37
|
});
|
|
37
38
|
}
|
|
38
39
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// Node imports
|
|
2
2
|
|
|
3
3
|
// Third party imports
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { GoogleAuth, type JWTInput } from "google-auth-library";
|
|
5
|
+
import { type H3Event, createError, defineEventHandler, readBody } from "h3";
|
|
6
6
|
import { ServicesClient } from "@google-cloud/run";
|
|
7
7
|
|
|
8
8
|
// Local imports
|
|
@@ -12,17 +12,52 @@ interface RunCloudBody {
|
|
|
12
12
|
email: string;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
|
|
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) => {
|
|
16
22
|
try {
|
|
17
23
|
const { email } = await readBody<RunCloudBody>(event);
|
|
18
24
|
console.log("[RUN CLOUD] Received request to create backend for email:", email);
|
|
19
|
-
|
|
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
|
+
|
|
20
55
|
const location = "europe-west9";
|
|
21
|
-
const projectId = process.env.GOOGLE_CLOUD_PROJECT;
|
|
22
|
-
const projectName = process.env.PROJECT as string;
|
|
23
56
|
const parent = `projects/${projectId}/locations/${location}`;
|
|
24
57
|
console.log({ parent });
|
|
58
|
+
|
|
25
59
|
const auth = new GoogleAuth({
|
|
60
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
26
61
|
credentials,
|
|
27
62
|
scopes: ["https://www.googleapis.com/auth/cloud-platform"],
|
|
28
63
|
});
|
|
@@ -30,21 +65,28 @@ export default defineEventHandler(async (event) => {
|
|
|
30
65
|
const image = await artifactImage(parent, authClient);
|
|
31
66
|
const request = requestConfig(parent, image, email, projectName);
|
|
32
67
|
console.log({ request });
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const runClient = new ServicesClient({ authClient: authClient as never });
|
|
68
|
+
|
|
69
|
+
const runClient = new ServicesClient({ authClient });
|
|
36
70
|
const [operation] = await runClient.createService(request);
|
|
37
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
|
+
|
|
38
80
|
console.log("Service URL created:", response.uri);
|
|
39
81
|
return {
|
|
40
82
|
statusCode: 200,
|
|
41
|
-
url:
|
|
83
|
+
url: response.uri.replace(/^https?:\/\//iu, ""),
|
|
42
84
|
};
|
|
43
85
|
} catch (error) {
|
|
44
86
|
console.log(error);
|
|
45
87
|
throw createError({
|
|
46
88
|
statusCode: 500,
|
|
47
|
-
statusMessage:
|
|
89
|
+
statusMessage: error instanceof Error ? error.message : String(error),
|
|
48
90
|
});
|
|
49
91
|
}
|
|
50
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";
|
|
@@ -13,7 +13,7 @@ interface ExtensionsConfigSchema {
|
|
|
13
13
|
extensions: Record<string, { path: string }>;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
function projectConf(projectName: string) {
|
|
16
|
+
function projectConf(projectName: string): Conf<ExtensionsConfigSchema> {
|
|
17
17
|
const projectConfig = new Conf<ExtensionsConfigSchema>({
|
|
18
18
|
projectName,
|
|
19
19
|
});
|
|
@@ -22,45 +22,42 @@ function projectConf(projectName: string) {
|
|
|
22
22
|
});
|
|
23
23
|
return projectConfig;
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
|
|
26
|
+
function confFolderPath(projectName: string): string {
|
|
26
27
|
const projectConfig = projectConf(projectName);
|
|
27
28
|
return path.dirname(projectConfig.path);
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
+
|
|
31
|
+
function targetExtensionFilePath(projectName: string, filename: string): string {
|
|
30
32
|
const safeFilename = sanitize(filename);
|
|
31
33
|
const targetPath = path.join(confFolderPath(projectName), safeFilename);
|
|
32
34
|
return targetPath;
|
|
33
35
|
}
|
|
34
|
-
|
|
36
|
+
|
|
37
|
+
function extensionsConf(projectName: string): ExtensionsConfigSchema["extensions"] {
|
|
35
38
|
const projectConfig = projectConf(projectName);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
const extensionsConfig = projectConfig.get("extensions");
|
|
40
|
-
return extensionsConfig;
|
|
39
|
+
// Read-only: concurrent app instances share this file and racing writes fail on Windows (EPERM)
|
|
40
|
+
return projectConfig.get("extensions", {});
|
|
41
41
|
}
|
|
42
|
+
|
|
42
43
|
function addExtensionToConf(
|
|
43
44
|
projectName: string,
|
|
44
45
|
{ extensionId, extensionPath }: { extensionId: string; extensionPath: string },
|
|
45
|
-
) {
|
|
46
|
+
): void {
|
|
46
47
|
const projectConfig = projectConf(projectName);
|
|
47
48
|
projectConfig.set(`extensions.${extensionId}.path`, extensionPath);
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
function extensionPathFromConf(projectName: string, extensionId: string): string {
|
|
51
52
|
const projectConfig = projectConf(projectName);
|
|
52
|
-
return projectConfig.get(`extensions.${extensionId}.path`)
|
|
53
|
+
return projectConfig.get(`extensions.${extensionId}.path`);
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
async function removeExtensionFromConf(projectName: string, extensionId: string) {
|
|
56
|
+
async function removeExtensionFromConf(projectName: string, extensionId: string): Promise<void> {
|
|
56
57
|
const projectConfig = projectConf(projectName);
|
|
57
58
|
const extensionArchivePath = extensionPathFromConf(projectName, extensionId);
|
|
58
|
-
await unlink(extensionArchivePath
|
|
59
|
-
|
|
60
|
-
throw error;
|
|
61
|
-
}
|
|
62
|
-
console.log(`${extensionArchivePath} was deleted`);
|
|
63
|
-
});
|
|
59
|
+
await unlink(extensionArchivePath);
|
|
60
|
+
console.log(`${extensionArchivePath} was deleted`);
|
|
64
61
|
projectConfig.delete(`extensions.${extensionId}`);
|
|
65
62
|
console.log(`${extensionId} was deleted from ${projectName} config`);
|
|
66
63
|
}
|
|
@@ -70,20 +67,30 @@ interface ExtensionMetadata {
|
|
|
70
67
|
[key: string]: unknown;
|
|
71
68
|
}
|
|
72
69
|
|
|
73
|
-
|
|
70
|
+
function isExtensionMetadata(value: unknown): value is ExtensionMetadata {
|
|
71
|
+
return (
|
|
72
|
+
typeof value === "object" && value !== null && "id" in value && typeof value.id === "string"
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function registerExtensionFile(projectName: string, file: string): Promise<void> {
|
|
74
77
|
const StreamZipAsync = StreamZip.async;
|
|
75
78
|
const zip = new StreamZipAsync({
|
|
76
79
|
file,
|
|
77
80
|
storeEntries: true,
|
|
78
81
|
});
|
|
79
82
|
const metadataJson = await zip.entryData("metadata.json");
|
|
80
|
-
const
|
|
81
|
-
|
|
83
|
+
const parsedMetadata: unknown = JSON.parse(metadataJson.toString("utf8"));
|
|
84
|
+
if (!isExtensionMetadata(parsedMetadata)) {
|
|
85
|
+
throw new TypeError("metadata.json does not match the expected ExtensionMetadata shape");
|
|
86
|
+
}
|
|
87
|
+
const { id } = parsedMetadata;
|
|
82
88
|
addExtensionToConf(projectName, {
|
|
83
89
|
extensionId: id,
|
|
84
90
|
extensionPath: file,
|
|
85
91
|
});
|
|
86
92
|
}
|
|
93
|
+
|
|
87
94
|
export {
|
|
88
95
|
addExtensionToConf,
|
|
89
96
|
confFolderPath,
|
package/server/utils/cleanup.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference path="../types/vendor.d.ts" />
|
|
2
1
|
// Node imports
|
|
3
2
|
import fs from "node:fs";
|
|
4
3
|
import path from "node:path";
|
|
@@ -18,6 +17,7 @@ interface Microservice {
|
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
const MAX_DELETE_FOLDER_RETRIES = 5;
|
|
20
|
+
|
|
21
21
|
async function deleteFolderRecursive(folderPath: string): Promise<void> {
|
|
22
22
|
if (!fs.existsSync(folderPath)) {
|
|
23
23
|
console.log(`Folder ${folderPath} does not exist.`);
|
|
@@ -32,7 +32,6 @@ async function deleteFolderRecursive(folderPath: string): Promise<void> {
|
|
|
32
32
|
return;
|
|
33
33
|
} catch (error) {
|
|
34
34
|
console.error(`Error deleting folder ${folderPath}:`, error);
|
|
35
|
-
// Wait before retrying
|
|
36
35
|
const MILLISECONDS_PER_RETRY = 1000;
|
|
37
36
|
const DELAY = MILLISECONDS_PER_RETRY * (i + 1);
|
|
38
37
|
// oxlint-disable-next-line no-await-in-loop
|
|
@@ -44,35 +43,54 @@ async function deleteFolderRecursive(folderPath: string): Promise<void> {
|
|
|
44
43
|
`Failed to delete folder ${folderPath} after ${MAX_DELETE_FOLDER_RETRIES} retries`,
|
|
45
44
|
);
|
|
46
45
|
}
|
|
47
|
-
|
|
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> {
|
|
48
57
|
console.log("killHttpMicroservice", {
|
|
49
58
|
...microservice,
|
|
50
59
|
});
|
|
51
60
|
const failMessage = `Failed to kill ${microservice.name}`;
|
|
52
|
-
async function do_kill() {
|
|
61
|
+
async function do_kill(): Promise<void> {
|
|
62
|
+
if (microservice.url === undefined) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
53
65
|
try {
|
|
54
|
-
await fetch(microservice.url
|
|
66
|
+
await fetch(microservice.url, {
|
|
55
67
|
method: microservice.method,
|
|
56
68
|
});
|
|
57
69
|
} catch (error) {
|
|
58
|
-
|
|
70
|
+
const message = isErrorWithMessage(error) ? error.message : String(error);
|
|
71
|
+
console.log(`Expected error during kill of ${microservice.name}:`, message);
|
|
59
72
|
}
|
|
60
73
|
}
|
|
61
|
-
|
|
74
|
+
await pTimeout(do_kill(), {
|
|
62
75
|
milliseconds: 5000,
|
|
63
76
|
message: failMessage,
|
|
64
77
|
});
|
|
65
78
|
}
|
|
66
|
-
|
|
79
|
+
|
|
80
|
+
async function killWebsocketMicroservice(microservice: Microservice): Promise<void> {
|
|
67
81
|
console.log("killWebsocketMicroservice", {
|
|
68
82
|
...microservice,
|
|
69
83
|
});
|
|
70
84
|
const failMessage = `Failed to kill ${microservice.name}`;
|
|
71
85
|
const successMessage = `Disconnected from ${microservice.name} WebSocket server`;
|
|
72
|
-
function do_kill() {
|
|
86
|
+
async function do_kill(): Promise<void> {
|
|
87
|
+
if (microservice.url === undefined) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const socketUrl = microservice.url;
|
|
73
91
|
// oxlint-disable-next-line promise/avoid-new
|
|
74
|
-
|
|
75
|
-
const socket = new WebSocket(
|
|
92
|
+
await new Promise<void>((resolve) => {
|
|
93
|
+
const socket = new WebSocket(socketUrl);
|
|
76
94
|
socket.on("open", () => {
|
|
77
95
|
console.log("Connected to WebSocket server");
|
|
78
96
|
socket.send(
|
|
@@ -87,7 +105,7 @@ function killWebsocketMicroservice(microservice: Microservice): Promise<void> {
|
|
|
87
105
|
}),
|
|
88
106
|
);
|
|
89
107
|
});
|
|
90
|
-
socket.on("message", (data) => {
|
|
108
|
+
socket.on("message", (data: Buffer | string) => {
|
|
91
109
|
const message = data.toString();
|
|
92
110
|
console.log("Received from server:", message);
|
|
93
111
|
if (message.includes("hello")) {
|
|
@@ -106,46 +124,54 @@ function killWebsocketMicroservice(microservice: Microservice): Promise<void> {
|
|
|
106
124
|
console.log(successMessage);
|
|
107
125
|
resolve();
|
|
108
126
|
});
|
|
109
|
-
socket.on("error", (error) => {
|
|
127
|
+
socket.on("error", (error: Error) => {
|
|
110
128
|
console.error("WebSocket error:", error);
|
|
111
129
|
socket.close();
|
|
112
130
|
resolve();
|
|
113
131
|
});
|
|
114
132
|
});
|
|
115
133
|
}
|
|
116
|
-
|
|
134
|
+
await pTimeout(do_kill(), {
|
|
117
135
|
milliseconds: 5000,
|
|
118
136
|
message: failMessage,
|
|
119
137
|
});
|
|
120
138
|
}
|
|
139
|
+
|
|
121
140
|
async function killMicroservice(microservice: Microservice): Promise<void> {
|
|
122
141
|
if (microservice.type === "back") {
|
|
123
142
|
await killHttpMicroservice(microservice);
|
|
124
143
|
} else if (microservice.type === "viewer") {
|
|
125
144
|
await killWebsocketMicroservice(microservice);
|
|
126
145
|
} else {
|
|
127
|
-
|
|
146
|
+
const exhaustiveCheck: never = microservice.type;
|
|
147
|
+
throw new Error(`Unknown microservice type: ${String(exhaustiveCheck)}`);
|
|
128
148
|
}
|
|
129
149
|
}
|
|
130
|
-
|
|
150
|
+
|
|
151
|
+
async function killMicroservices(microservices: readonly Microservice[]): Promise<Microservice[]> {
|
|
131
152
|
console.log("killMicroservices", {
|
|
132
153
|
microservices,
|
|
133
154
|
});
|
|
134
155
|
const results = await Promise.allSettled(
|
|
135
|
-
microservices.map((microservice) =>
|
|
156
|
+
microservices.map(async (microservice) => {
|
|
157
|
+
await killMicroservice(microservice);
|
|
158
|
+
}),
|
|
136
159
|
);
|
|
137
|
-
|
|
138
|
-
for (let i = 0; i < killed.length; i += 1) {
|
|
139
|
-
const microservice = microservices[i];
|
|
140
|
-
if (microservice) {
|
|
141
|
-
microservices.splice(microservices.indexOf(microservice), 1);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
160
|
+
return microservices.filter((_, index) => results[index]?.status !== "fulfilled");
|
|
144
161
|
}
|
|
162
|
+
|
|
145
163
|
function microservicesMetadatasPath(projectFolderPath: string): string {
|
|
146
164
|
return path.join(projectFolderPath, "microservices.json");
|
|
147
165
|
}
|
|
148
166
|
|
|
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
|
+
|
|
149
175
|
function projectMicroservices(projectFolderPath: string): Microservice[] {
|
|
150
176
|
console.log("projectMicroservices", {
|
|
151
177
|
projectFolderPath,
|
|
@@ -157,11 +183,13 @@ function projectMicroservices(projectFolderPath: string): Microservice[] {
|
|
|
157
183
|
};
|
|
158
184
|
fs.writeFileSync(filePath, JSON.stringify(microservicesMetadatas, undefined, 2), "utf8");
|
|
159
185
|
}
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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;
|
|
164
191
|
}
|
|
192
|
+
|
|
165
193
|
async function cleanupBackend(projectFolderPath: string): Promise<void> {
|
|
166
194
|
if (!fs.existsSync(projectFolderPath)) {
|
|
167
195
|
console.log(`Folder ${projectFolderPath} does not exist. Skipping cleanup.`);
|
|
@@ -171,11 +199,13 @@ async function cleanupBackend(projectFolderPath: string): Promise<void> {
|
|
|
171
199
|
await killMicroservices(microservices);
|
|
172
200
|
await deleteFolderRecursive(projectFolderPath);
|
|
173
201
|
}
|
|
202
|
+
|
|
174
203
|
function getMicroserviceByName(
|
|
175
|
-
microservices: Microservice[],
|
|
204
|
+
microservices: readonly Microservice[],
|
|
176
205
|
name: string,
|
|
177
206
|
): Microservice | undefined {
|
|
178
|
-
|
|
207
|
+
const found = microservices.find((microservice) => microservice.name === name);
|
|
208
|
+
return found === undefined ? undefined : { ...found };
|
|
179
209
|
}
|
|
180
210
|
|
|
181
211
|
export {
|
package/server/utils/cloud.ts
CHANGED
|
@@ -4,25 +4,23 @@ 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";
|
|
8
9
|
import type { protos } from "@google-cloud/run";
|
|
9
10
|
|
|
10
11
|
// Local imports
|
|
11
12
|
|
|
12
|
-
// The googleapis package's per-API-version `auth` option types don't line up with the concrete client returned by `GoogleAuth.getClient()` (they're structurally close but not nominally assignable). `any` matches how googleapis treats it at runtime (duck typed).
|
|
13
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
-
type GoogleAuthClient = any;
|
|
15
|
-
// `v2` is a namespace segment in the `@google-cloud/run` package's own generated protobuf types, not a name this codebase declares.
|
|
16
13
|
// oxlint-disable-next-line eslint/id-length
|
|
17
14
|
type CreateServiceRequest = protos.google.cloud.run.v2.ICreateServiceRequest;
|
|
18
15
|
|
|
19
16
|
const LOCATIONS_DIR = "/etc/nginx/locations";
|
|
20
17
|
|
|
21
|
-
async function artifactImage(parent: string, authClient:
|
|
18
|
+
async function artifactImage(parent: string, authClient: AuthClient): Promise<string> {
|
|
22
19
|
const projectName = process.env.PROJECT;
|
|
23
20
|
const registry = google.artifactregistry({
|
|
24
21
|
version: "v1",
|
|
25
|
-
|
|
22
|
+
// oxlint-disable-next-line typescript/no-unsafe-type-assertion
|
|
23
|
+
auth: authClient as OAuth2Client,
|
|
26
24
|
});
|
|
27
25
|
const branch = process.env.NETLIFY_BRANCH;
|
|
28
26
|
const [, projectId] = parent.split("/");
|
|
@@ -86,7 +84,6 @@ function requestConfig(
|
|
|
86
84
|
image,
|
|
87
85
|
ports: [
|
|
88
86
|
{
|
|
89
|
-
name: "h2c",
|
|
90
87
|
containerPort: 80,
|
|
91
88
|
},
|
|
92
89
|
],
|
|
@@ -112,7 +109,11 @@ function requestConfig(
|
|
|
112
109
|
};
|
|
113
110
|
}
|
|
114
111
|
|
|
115
|
-
function addSupervisorProgram(
|
|
112
|
+
function addSupervisorProgram(
|
|
113
|
+
name: string,
|
|
114
|
+
command: string,
|
|
115
|
+
executableArgs: readonly string[],
|
|
116
|
+
): void {
|
|
116
117
|
const conf = `
|
|
117
118
|
[program:${name}]
|
|
118
119
|
command=${command} ${executableArgs.join(" ")}
|