@geode/opengeodeweb-front 10.34.0-rc.9 → 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
|
@@ -1,6 +1,7 @@
|
|
|
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";
|
|
@@ -8,14 +9,17 @@ import { createError } from "h3";
|
|
|
8
9
|
// Local imports
|
|
9
10
|
import { extensionFrontendPath } from "@geode/opengeodeweb-front/server/utils/path.ts";
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
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>;
|
|
19
23
|
|
|
20
24
|
async function readExtensionMetadata(unzippedExtensionPath: string): Promise<ExtensionMetadata> {
|
|
21
25
|
const metadataPath = path.join(unzippedExtensionPath, "metadata.json");
|
|
@@ -26,7 +30,17 @@ async function readExtensionMetadata(unzippedExtensionPath: string): Promise<Ext
|
|
|
26
30
|
statusMessage: "Invalid extension file: missing metadata.json",
|
|
27
31
|
});
|
|
28
32
|
}
|
|
29
|
-
|
|
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
|
+
|
|
30
44
|
console.log("readExtensionMetadata", { metadata });
|
|
31
45
|
if (!metadata.frontendFile) {
|
|
32
46
|
throw createError({
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// Not auto-fixable (eslint's sort-imports core rule has no autofixer) and this file's import order doesn't match its syntax-kind-then-alphabetical requirement - left as-is rather than manually reordered across the codebase for a purely cosmetic rule.
|
|
2
|
-
// oxlint-disable eslint/sort-imports
|
|
3
1
|
// Node imports
|
|
4
2
|
import child_process from "node:child_process";
|
|
5
3
|
import fs from "node:fs";
|
|
@@ -9,13 +7,9 @@ import path from "node:path";
|
|
|
9
7
|
import back_schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json" with { type: "json" };
|
|
10
8
|
|
|
11
9
|
// Local imports
|
|
10
|
+
import { type Microservice, microservicesMetadatasPath, projectMicroservices } from "./cleanup.js";
|
|
11
|
+
import { type NamedChildProcess, getAvailablePort, waitForReady } from "./scripts.js";
|
|
12
12
|
import { addNginxLocation, addSupervisorProgram } from "./cloud.js";
|
|
13
|
-
import { getAvailablePort, waitForReady } from "./scripts.js";
|
|
14
|
-
// oxlint-disable-next-line eslint/no-duplicate-imports
|
|
15
|
-
import type { NamedChildProcess } from "./scripts.js";
|
|
16
|
-
import { microservicesMetadatasPath, projectMicroservices } from "./cleanup.js";
|
|
17
|
-
// oxlint-disable-next-line eslint/no-duplicate-imports
|
|
18
|
-
import type { Microservice } from "./cleanup.js";
|
|
19
13
|
import { executablePath } from "./path.js";
|
|
20
14
|
|
|
21
15
|
interface RunArgs {
|
|
@@ -28,10 +22,11 @@ const MILLISECONDS_PER_SECOND = 1000;
|
|
|
28
22
|
const DEFAULT_TIMEOUT_SECONDS = 45;
|
|
29
23
|
const MAX_PORT_RETRIES = 1;
|
|
30
24
|
const DEFAULT_RUN_ARGS: RunArgs = { projectFolderPath: "" };
|
|
25
|
+
|
|
31
26
|
async function runScript(
|
|
32
27
|
execPath: string,
|
|
33
28
|
execName: string,
|
|
34
|
-
args: string[],
|
|
29
|
+
args: readonly string[],
|
|
35
30
|
expectedResponse: string,
|
|
36
31
|
timeoutSeconds = DEFAULT_TIMEOUT_SECONDS,
|
|
37
32
|
): Promise<NamedChildProcess> {
|
|
@@ -45,7 +40,9 @@ async function runScript(
|
|
|
45
40
|
console.log(`[${child.name}] spawned, pid=${child.pid}`);
|
|
46
41
|
});
|
|
47
42
|
const controller = new AbortController();
|
|
48
|
-
const timer = setTimeout(() =>
|
|
43
|
+
const timer = setTimeout(() => {
|
|
44
|
+
controller.abort();
|
|
45
|
+
}, timeoutSeconds * MILLISECONDS_PER_SECOND);
|
|
49
46
|
if (typeof timer.unref === "function") {
|
|
50
47
|
timer.unref();
|
|
51
48
|
}
|
|
@@ -59,6 +56,7 @@ async function runScript(
|
|
|
59
56
|
throw error;
|
|
60
57
|
}
|
|
61
58
|
}
|
|
59
|
+
|
|
62
60
|
function isPortInUseError(error: unknown): boolean {
|
|
63
61
|
return /EADDRINUSE|address already in use|port already in use/iu.test(String(error));
|
|
64
62
|
}
|
|
@@ -68,7 +66,10 @@ function backArgs(args: RunArgs, port: number): string[] {
|
|
|
68
66
|
if (!projectFolderPath) {
|
|
69
67
|
throw new Error("projectFolderPath is required");
|
|
70
68
|
}
|
|
71
|
-
const uploadFolderPath =
|
|
69
|
+
const uploadFolderPath =
|
|
70
|
+
args.uploadFolderPath !== undefined && args.uploadFolderPath !== ""
|
|
71
|
+
? args.uploadFolderPath
|
|
72
|
+
: path.join(projectFolderPath, "uploads");
|
|
72
73
|
const executableArgs = [
|
|
73
74
|
"--port",
|
|
74
75
|
String(port),
|
|
@@ -81,7 +82,7 @@ function backArgs(args: RunArgs, port: number): string[] {
|
|
|
81
82
|
"--timeout",
|
|
82
83
|
"0",
|
|
83
84
|
];
|
|
84
|
-
if (process.env.NODE_ENV ===
|
|
85
|
+
if (process.env.NODE_ENV === undefined || process.env.NODE_ENV === "development") {
|
|
85
86
|
executableArgs.push("--debug");
|
|
86
87
|
}
|
|
87
88
|
return executableArgs;
|
|
@@ -92,7 +93,7 @@ async function runBack(
|
|
|
92
93
|
execPath: string,
|
|
93
94
|
args: RunArgs = DEFAULT_RUN_ARGS,
|
|
94
95
|
attempts = 0,
|
|
95
|
-
): Promise<number
|
|
96
|
+
): Promise<number> {
|
|
96
97
|
let port: number | undefined = undefined;
|
|
97
98
|
try {
|
|
98
99
|
port = await getAvailablePort();
|
|
@@ -111,7 +112,7 @@ async function runBack(
|
|
|
111
112
|
return newPort;
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
|
-
|
|
115
|
+
throw new Error(`runBack failed to run ${execName}`);
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
async function runViewer(
|
|
@@ -119,7 +120,7 @@ async function runViewer(
|
|
|
119
120
|
execPath: string,
|
|
120
121
|
args: RunArgs = DEFAULT_RUN_ARGS,
|
|
121
122
|
attempts = 0,
|
|
122
|
-
): Promise<number
|
|
123
|
+
): Promise<number> {
|
|
123
124
|
const { projectFolderPath } = args;
|
|
124
125
|
if (!projectFolderPath) {
|
|
125
126
|
throw new Error("projectFolderPath is required");
|
|
@@ -140,7 +141,7 @@ async function runViewer(
|
|
|
140
141
|
return port;
|
|
141
142
|
} catch (error) {
|
|
142
143
|
if (!isPortInUseError(error)) {
|
|
143
|
-
console.log("
|
|
144
|
+
console.log("runViewer error", error);
|
|
144
145
|
throw error;
|
|
145
146
|
}
|
|
146
147
|
if (attempts <= MAX_PORT_RETRIES) {
|
|
@@ -149,7 +150,7 @@ async function runViewer(
|
|
|
149
150
|
return newPort;
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
|
-
|
|
153
|
+
throw new Error(`runViewer failed to run ${execName}`);
|
|
153
154
|
}
|
|
154
155
|
|
|
155
156
|
async function runExtension(
|
|
@@ -158,7 +159,7 @@ async function runExtension(
|
|
|
158
159
|
execPath: string,
|
|
159
160
|
args: RunArgs = DEFAULT_RUN_ARGS,
|
|
160
161
|
attempts = 0,
|
|
161
|
-
): Promise<number
|
|
162
|
+
): Promise<number> {
|
|
162
163
|
let port: number | undefined = undefined;
|
|
163
164
|
try {
|
|
164
165
|
port = await getAvailablePort();
|
|
@@ -170,7 +171,7 @@ async function runExtension(
|
|
|
170
171
|
return port;
|
|
171
172
|
} catch (error) {
|
|
172
173
|
if (!isPortInUseError(error)) {
|
|
173
|
-
console.log("
|
|
174
|
+
console.log("runExtension error", error);
|
|
174
175
|
throw error;
|
|
175
176
|
}
|
|
176
177
|
if (attempts <= MAX_PORT_RETRIES) {
|
|
@@ -179,19 +180,26 @@ async function runExtension(
|
|
|
179
180
|
return newPort;
|
|
180
181
|
}
|
|
181
182
|
}
|
|
182
|
-
|
|
183
|
+
throw new Error(`runExtension failed to run ${extensionId}`);
|
|
183
184
|
}
|
|
184
185
|
function addMicroserviceMetadatas(projectFolderPath: string, serviceObj: Microservice): void {
|
|
185
186
|
const microservices = projectMicroservices(projectFolderPath);
|
|
187
|
+
let enriched: Microservice = { ...serviceObj };
|
|
186
188
|
if (serviceObj.type === "back") {
|
|
187
189
|
const schema = back_schemas.opengeodeweb_back.kill;
|
|
188
|
-
serviceObj.url = `http://localhost:${serviceObj.port}/${schema.$id}`;
|
|
189
190
|
const [method] = schema.methods;
|
|
190
|
-
|
|
191
|
+
enriched = {
|
|
192
|
+
...enriched,
|
|
193
|
+
url: `http://localhost:${serviceObj.port}/${schema.$id}`,
|
|
194
|
+
method,
|
|
195
|
+
};
|
|
191
196
|
} else if (serviceObj.type === "viewer") {
|
|
192
|
-
|
|
197
|
+
enriched = {
|
|
198
|
+
...enriched,
|
|
199
|
+
url: `ws://localhost:${serviceObj.port}/ws`,
|
|
200
|
+
};
|
|
193
201
|
}
|
|
194
|
-
microservices.push(
|
|
202
|
+
microservices.push(enriched);
|
|
195
203
|
fs.writeFileSync(
|
|
196
204
|
microservicesMetadatasPath(projectFolderPath),
|
|
197
205
|
JSON.stringify(
|
|
@@ -203,4 +211,5 @@ function addMicroserviceMetadatas(projectFolderPath: string, serviceObj: Microse
|
|
|
203
211
|
),
|
|
204
212
|
);
|
|
205
213
|
}
|
|
214
|
+
|
|
206
215
|
export { addMicroserviceMetadatas, runBack, runExtension, runViewer };
|
package/server/utils/path.ts
CHANGED
|
@@ -53,13 +53,13 @@ function executablePath(execPath: string, execName: string): string {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
const foundAtExecPath = findExecutableInDir(execPath, execName, osExecutableName);
|
|
56
|
-
if (foundAtExecPath) {
|
|
56
|
+
if (foundAtExecPath !== undefined && foundAtExecPath !== "") {
|
|
57
57
|
return foundAtExecPath;
|
|
58
58
|
}
|
|
59
59
|
if (mode === appMode.DESKTOP && nodeEnv === "production") {
|
|
60
|
-
if (resourcesPath) {
|
|
60
|
+
if (resourcesPath !== undefined && resourcesPath !== "") {
|
|
61
61
|
const foundInResources = findExecutableInDir(resourcesPath, execName, osExecutableName);
|
|
62
|
-
if (foundInResources) {
|
|
62
|
+
if (foundInResources !== undefined && foundInResources !== "") {
|
|
63
63
|
return foundInResources;
|
|
64
64
|
}
|
|
65
65
|
}
|
|
@@ -140,7 +140,7 @@ async function extensionFrontendPath(
|
|
|
140
140
|
extentionRepoName,
|
|
141
141
|
frontendFile,
|
|
142
142
|
);
|
|
143
|
-
if (localFilePath) {
|
|
143
|
+
if (localFilePath !== undefined && localFilePath !== "") {
|
|
144
144
|
return localFilePath;
|
|
145
145
|
}
|
|
146
146
|
const unzippedfrontendFilePath = path.join(unzippedExtensionPath, frontendFile);
|
package/server/utils/scripts.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
// Not auto-fixable (eslint's sort-imports core rule has no autofixer) and this file's import order doesn't match its syntax-kind-then-alphabetical requirement - left as-is rather than manually reordered across the codebase for a purely cosmetic rule.
|
|
2
|
-
// oxlint-disable eslint/sort-imports
|
|
3
1
|
// Node imports
|
|
2
|
+
import type { Readable } from "node:stream";
|
|
4
3
|
import child_process from "node:child_process";
|
|
5
4
|
import fs from "node:fs";
|
|
6
5
|
import { on } from "node:events";
|
|
7
6
|
import path from "node:path";
|
|
8
7
|
import readline from "node:readline";
|
|
9
|
-
import type { Readable } from "node:stream";
|
|
10
8
|
|
|
11
9
|
// Third party imports
|
|
12
10
|
import { getPort } from "get-port-please";
|
|
@@ -18,19 +16,23 @@ import { setAppBaseUrl } from "@geode/opengeodeweb-front/shared/scripts.ts";
|
|
|
18
16
|
const BYTES_PER_KIBIBYTE = 1024;
|
|
19
17
|
const MAX_ERROR_BUFFER_KIBIBYTES = 64;
|
|
20
18
|
const MAX_ERROR_BUFFER_BYTES = MAX_ERROR_BUFFER_KIBIBYTES * BYTES_PER_KIBIBYTE;
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
|
|
20
|
+
async function getAvailablePort(): Promise<number> {
|
|
21
|
+
const port = await getPort({
|
|
23
22
|
host: "localhost",
|
|
24
23
|
random: true,
|
|
25
24
|
});
|
|
25
|
+
return port;
|
|
26
26
|
}
|
|
27
|
+
|
|
27
28
|
function commandExistsSync(execName: string): boolean {
|
|
28
|
-
const envPath = process.env.PATH
|
|
29
|
+
const envPath = process.env.PATH ?? "";
|
|
29
30
|
return envPath.split(path.delimiter).some((directory) => {
|
|
30
31
|
const filePath = path.join(directory, execName);
|
|
31
32
|
return fs.existsSync(filePath) && fs.statSync(filePath).isFile();
|
|
32
33
|
});
|
|
33
34
|
}
|
|
35
|
+
|
|
34
36
|
const encoder = new TextEncoder();
|
|
35
37
|
function byteLength(str: string): number {
|
|
36
38
|
return encoder.encode(str).byteLength;
|
|
@@ -40,8 +42,8 @@ interface NamedChildProcess extends child_process.ChildProcessByStdio<null, Read
|
|
|
40
42
|
name?: string;
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
// oxlint-disable-next-line max-lines-per-function
|
|
44
|
-
function waitForReady(
|
|
45
|
+
// oxlint-disable-next-line max-lines-per-function typescript/prefer-readonly-parameter-types eslint/require-await
|
|
46
|
+
async function waitForReady(
|
|
45
47
|
child: NamedChildProcess,
|
|
46
48
|
expectedResponse: string,
|
|
47
49
|
signal?: AbortSignal,
|
|
@@ -55,7 +57,7 @@ function waitForReady(
|
|
|
55
57
|
input: child.stderr,
|
|
56
58
|
});
|
|
57
59
|
let recentOutput = "";
|
|
58
|
-
function recordOutput(lineOutput: string) {
|
|
60
|
+
function recordOutput(lineOutput: string): void {
|
|
59
61
|
const safeLine =
|
|
60
62
|
byteLength(lineOutput) > MAX_ERROR_BUFFER_BYTES / 2
|
|
61
63
|
? `${lineOutput.slice(0, MAX_ERROR_BUFFER_BYTES / 2)}…[truncated]`
|
|
@@ -76,7 +78,7 @@ function waitForReady(
|
|
|
76
78
|
let onClose: ((code: number | null) => void) | undefined = undefined;
|
|
77
79
|
let onAbort: (() => void) | undefined = undefined;
|
|
78
80
|
|
|
79
|
-
function cleanup() {
|
|
81
|
+
function cleanup(): void {
|
|
80
82
|
if (onLine) {
|
|
81
83
|
readlineStdout.removeListener("line", onLine);
|
|
82
84
|
}
|
|
@@ -94,7 +96,7 @@ function waitForReady(
|
|
|
94
96
|
}
|
|
95
97
|
}
|
|
96
98
|
|
|
97
|
-
function becomeReady() {
|
|
99
|
+
function becomeReady(): void {
|
|
98
100
|
cleanup();
|
|
99
101
|
readlineStdout.on("line", (line) => {
|
|
100
102
|
console.log(`[${child.name}] ${line}`);
|
|
@@ -108,7 +110,7 @@ function waitForReady(
|
|
|
108
110
|
resolve(child);
|
|
109
111
|
}
|
|
110
112
|
|
|
111
|
-
onLine = (lineOutput) => {
|
|
113
|
+
onLine = (lineOutput): void => {
|
|
112
114
|
console.log(`[${child.name}] ${lineOutput}`);
|
|
113
115
|
recordOutput(lineOutput);
|
|
114
116
|
if (lineOutput.includes(expectedResponse)) {
|
|
@@ -116,7 +118,7 @@ function waitForReady(
|
|
|
116
118
|
}
|
|
117
119
|
};
|
|
118
120
|
|
|
119
|
-
onErrLine = (line) => {
|
|
121
|
+
onErrLine = (line): void => {
|
|
120
122
|
console.log(`[${child.name}] ${line}`);
|
|
121
123
|
recordOutput(line);
|
|
122
124
|
if (line.includes(expectedResponse)) {
|
|
@@ -124,12 +126,12 @@ function waitForReady(
|
|
|
124
126
|
}
|
|
125
127
|
};
|
|
126
128
|
|
|
127
|
-
onError = (err) => {
|
|
129
|
+
onError = (err): void => {
|
|
128
130
|
cleanup();
|
|
129
131
|
reject(err);
|
|
130
132
|
};
|
|
131
133
|
|
|
132
|
-
onClose = (code) => {
|
|
134
|
+
onClose = (code): void => {
|
|
133
135
|
console.log(`[${child.name}] exited with code ${code}`);
|
|
134
136
|
cleanup();
|
|
135
137
|
reject(
|
|
@@ -139,7 +141,7 @@ function waitForReady(
|
|
|
139
141
|
);
|
|
140
142
|
};
|
|
141
143
|
|
|
142
|
-
onAbort = () => {
|
|
144
|
+
onAbort = (): void => {
|
|
143
145
|
cleanup();
|
|
144
146
|
reject(new Error(`[${child.name}] timed out waiting for "${expectedResponse}"`));
|
|
145
147
|
};
|
|
@@ -157,22 +159,23 @@ function waitForReady(
|
|
|
157
159
|
async function waitNuxt(
|
|
158
160
|
nuxtProcess: child_process.ChildProcessWithoutNullStreams,
|
|
159
161
|
): Promise<string> {
|
|
160
|
-
nuxtProcess.stderr.on("data", (data) => {
|
|
162
|
+
nuxtProcess.stderr.on("data", (data: Buffer) => {
|
|
161
163
|
console.log("Nuxt STDERR:", data.toString().trim());
|
|
162
164
|
});
|
|
163
165
|
nuxtProcess.on("close", (code) => {
|
|
164
166
|
console.log(`Nuxt process closed with code ${code}`);
|
|
165
167
|
});
|
|
166
168
|
for await (const [data] of on(nuxtProcess.stdout, "data")) {
|
|
167
|
-
const output = data
|
|
169
|
+
const output = String(data);
|
|
168
170
|
console.log("Nuxt STDOUT:", output.trim());
|
|
169
|
-
const portMatch =
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
const portMatch = /Listening on http:\/\/\[::\]:(?<port>\d+)/u.exec(output);
|
|
172
|
+
const port = portMatch?.groups?.port;
|
|
173
|
+
if (port !== undefined) {
|
|
174
|
+
console.log("Nuxt listening on port", port);
|
|
175
|
+
nuxtProcess.stdout.on("data", (newData: Buffer) => {
|
|
173
176
|
console.log("Nuxt STDOUT:", newData.toString().trim());
|
|
174
177
|
});
|
|
175
|
-
return
|
|
178
|
+
return port;
|
|
176
179
|
}
|
|
177
180
|
}
|
|
178
181
|
throw new Error("Nuxt process closed");
|
package/server/utils/server.ts
CHANGED
|
@@ -18,13 +18,13 @@ async function extractZipArchive(zipFilePath: string, outputDir: string): Promis
|
|
|
18
18
|
|
|
19
19
|
if (zipEntry.dir) {
|
|
20
20
|
promises.push(
|
|
21
|
-
(async () => {
|
|
21
|
+
(async (): Promise<void> => {
|
|
22
22
|
await fs.promises.mkdir(outputPath, { recursive: true });
|
|
23
23
|
})(),
|
|
24
24
|
);
|
|
25
25
|
} else {
|
|
26
26
|
promises.push(
|
|
27
|
-
(async () => {
|
|
27
|
+
(async (): Promise<void> => {
|
|
28
28
|
const content = await zipEntry.async("nodebuffer");
|
|
29
29
|
await fs.promises.mkdir(path.dirname(outputPath), {
|
|
30
30
|
recursive: true,
|
|
@@ -1,50 +1,64 @@
|
|
|
1
|
-
import { createServerWsRpcClient } from "./ws_client.js";
|
|
2
|
-
// oxlint-disable-next-line eslint/no-duplicate-imports
|
|
3
|
-
import type { ServerWsRpcClient } from "./ws_client.js";
|
|
1
|
+
import { type ServerWsRpcClient, createServerWsRpcClient } from "./ws_client.js";
|
|
4
2
|
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
const stringStorage = new Map<string, string>();
|
|
4
|
+
const booleanStorage = new Map<string, boolean>();
|
|
5
|
+
const clientStorage = new Map<string, ServerWsRpcClient>();
|
|
6
|
+
|
|
7
|
+
function getAppBaseUrl(): string {
|
|
8
|
+
const value = stringStorage.get("APP_BASE_URL");
|
|
9
|
+
if (value === undefined) {
|
|
10
|
+
throw new Error("APP_BASE_URL is not set");
|
|
11
|
+
}
|
|
12
|
+
return value;
|
|
8
13
|
}
|
|
9
|
-
function setAppBaseUrl(baseUrl: string) {
|
|
10
|
-
|
|
14
|
+
function setAppBaseUrl(baseUrl: string): void {
|
|
15
|
+
stringStorage.set("APP_BASE_URL", baseUrl);
|
|
11
16
|
}
|
|
12
|
-
function getBackBaseUrl():
|
|
13
|
-
|
|
17
|
+
function getBackBaseUrl(): string {
|
|
18
|
+
const value = stringStorage.get("BACK_BASE_URL");
|
|
19
|
+
if (value === undefined) {
|
|
20
|
+
throw new Error("BACK_BASE_URL is not set");
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
14
23
|
}
|
|
15
|
-
function setBackBaseUrl(baseUrl: string) {
|
|
16
|
-
|
|
24
|
+
function setBackBaseUrl(baseUrl: string): void {
|
|
25
|
+
stringStorage.set("BACK_BASE_URL", baseUrl);
|
|
17
26
|
}
|
|
18
|
-
function getViewerBaseUrl():
|
|
19
|
-
|
|
27
|
+
function getViewerBaseUrl(): string {
|
|
28
|
+
const value = stringStorage.get("VIEWER_BASE_URL");
|
|
29
|
+
if (value === undefined) {
|
|
30
|
+
throw new Error("VIEWER_BASE_URL is not set");
|
|
31
|
+
}
|
|
32
|
+
return value;
|
|
20
33
|
}
|
|
21
|
-
function setViewerBaseUrl(baseUrl: string) {
|
|
22
|
-
|
|
34
|
+
function setViewerBaseUrl(baseUrl: string): void {
|
|
35
|
+
stringStorage.set("VIEWER_BASE_URL", baseUrl);
|
|
23
36
|
}
|
|
24
|
-
function getIsAppReady():
|
|
25
|
-
return
|
|
37
|
+
function getIsAppReady(): boolean {
|
|
38
|
+
return booleanStorage.get("IS_APP_READY") ?? false;
|
|
26
39
|
}
|
|
27
|
-
function setIsAppReady(isAppReady: boolean) {
|
|
28
|
-
|
|
40
|
+
function setIsAppReady(isAppReady: boolean): void {
|
|
41
|
+
booleanStorage.set("IS_APP_READY", isAppReady);
|
|
29
42
|
}
|
|
30
43
|
async function setViewerWebSocketClient(baseUrl: string): Promise<ServerWsRpcClient> {
|
|
31
44
|
const client = createServerWsRpcClient(baseUrl);
|
|
32
45
|
client.onConnectionClose(() => {
|
|
33
|
-
if (
|
|
34
|
-
|
|
46
|
+
if (clientStorage.get("VIEWER_CLIENT") === client) {
|
|
47
|
+
clientStorage.delete("VIEWER_CLIENT");
|
|
35
48
|
}
|
|
36
49
|
});
|
|
37
50
|
await client.ready;
|
|
38
|
-
|
|
51
|
+
clientStorage.set("VIEWER_CLIENT", client);
|
|
39
52
|
return client;
|
|
40
53
|
}
|
|
41
54
|
async function getViewerWebSocketClient(): Promise<ServerWsRpcClient> {
|
|
42
|
-
const viewerClient =
|
|
43
|
-
if (viewerClient
|
|
55
|
+
const viewerClient = clientStorage.get("VIEWER_CLIENT");
|
|
56
|
+
if (viewerClient !== undefined && viewerClient.isOpen()) {
|
|
44
57
|
return viewerClient;
|
|
45
58
|
}
|
|
46
|
-
const viewerBaseUrl =
|
|
47
|
-
|
|
59
|
+
const viewerBaseUrl = getViewerBaseUrl();
|
|
60
|
+
const client = await setViewerWebSocketClient(viewerBaseUrl);
|
|
61
|
+
return client;
|
|
48
62
|
}
|
|
49
63
|
export {
|
|
50
64
|
getAppBaseUrl,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference path="../types/vendor.d.ts" />
|
|
2
1
|
// Third party imports
|
|
3
2
|
import { WebSocket } from "ws";
|
|
4
3
|
import { v4 as uuidv4 } from "uuid";
|
|
@@ -19,9 +18,29 @@ interface WsRpcMessage {
|
|
|
19
18
|
result?: unknown;
|
|
20
19
|
}
|
|
21
20
|
|
|
21
|
+
function isWsRpcMessage(value: unknown): value is WsRpcMessage {
|
|
22
|
+
return typeof value === "object" && value !== null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// oxlint-disable-next-line prefer-readonly-parameter-types
|
|
26
|
+
function rawDataToString(raw: WebSocket.RawData): string {
|
|
27
|
+
if (Buffer.isBuffer(raw)) {
|
|
28
|
+
return raw.toString();
|
|
29
|
+
}
|
|
30
|
+
if (Array.isArray(raw)) {
|
|
31
|
+
return Buffer.concat(raw).toString();
|
|
32
|
+
}
|
|
33
|
+
return Buffer.from(raw).toString();
|
|
34
|
+
}
|
|
35
|
+
|
|
22
36
|
interface ServerWsRpcClient {
|
|
23
37
|
call: (rpc: string, params?: Record<string, unknown>) => Promise<unknown>;
|
|
24
38
|
close: () => void;
|
|
39
|
+
getConnection: () => {
|
|
40
|
+
getSession: () => {
|
|
41
|
+
call: (rpc: string, params: readonly [Record<string, unknown>]) => Promise<unknown>;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
25
44
|
isOpen: () => boolean;
|
|
26
45
|
onConnectionClose: (callback: () => void) => void;
|
|
27
46
|
onConnectionError: (callback: (error: unknown) => void) => void;
|
|
@@ -35,7 +54,7 @@ function createServerWsRpcClient(baseUrl: string): ServerWsRpcClient {
|
|
|
35
54
|
let onCloseCallback: (() => void) | undefined = undefined;
|
|
36
55
|
let onErrorCallback: ((error: unknown) => void) | undefined = undefined;
|
|
37
56
|
|
|
38
|
-
//oxlint-disable-next-line promise/avoid-new
|
|
57
|
+
//oxlint-disable-next-line promise/avoid-new max-lines-per-function
|
|
39
58
|
const ready = new Promise<void>((resolve, reject) => {
|
|
40
59
|
socket.on("open", () => {
|
|
41
60
|
socket.send(
|
|
@@ -47,11 +66,15 @@ function createServerWsRpcClient(baseUrl: string): ServerWsRpcClient {
|
|
|
47
66
|
);
|
|
48
67
|
});
|
|
49
68
|
|
|
50
|
-
|
|
51
|
-
|
|
69
|
+
// oxlint-disable-next-line prefer-readonly-parameter-types
|
|
70
|
+
socket.on("message", (raw: WebSocket.RawData) => {
|
|
52
71
|
let message: WsRpcMessage | undefined = undefined;
|
|
53
72
|
try {
|
|
54
|
-
|
|
73
|
+
const parsed: unknown = JSON.parse(rawDataToString(raw));
|
|
74
|
+
if (!isWsRpcMessage(parsed)) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
message = parsed;
|
|
55
78
|
} catch {
|
|
56
79
|
return;
|
|
57
80
|
}
|
|
@@ -71,13 +94,13 @@ function createServerWsRpcClient(baseUrl: string): ServerWsRpcClient {
|
|
|
71
94
|
}
|
|
72
95
|
pending.delete(message.id);
|
|
73
96
|
if (message.error) {
|
|
74
|
-
entry.reject(new Error(message.error.message
|
|
97
|
+
entry.reject(new Error(message.error.message ?? "wslink RPC error"));
|
|
75
98
|
} else {
|
|
76
99
|
entry.resolve(message.result);
|
|
77
100
|
}
|
|
78
101
|
});
|
|
79
102
|
|
|
80
|
-
socket.on("error", (error) => {
|
|
103
|
+
socket.on("error", (error: Error) => {
|
|
81
104
|
onErrorCallback?.(error);
|
|
82
105
|
reject(error);
|
|
83
106
|
});
|
|
@@ -113,6 +136,17 @@ function createServerWsRpcClient(baseUrl: string): ServerWsRpcClient {
|
|
|
113
136
|
socket.close();
|
|
114
137
|
}
|
|
115
138
|
|
|
139
|
+
function getConnection(): ReturnType<ServerWsRpcClient["getConnection"]> {
|
|
140
|
+
return {
|
|
141
|
+
getSession: () => ({
|
|
142
|
+
call: async (rpc: string, [params]: readonly [Record<string, unknown>]) => {
|
|
143
|
+
const result = await call(rpc, params);
|
|
144
|
+
return result;
|
|
145
|
+
},
|
|
146
|
+
}),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
116
150
|
function isOpen(): boolean {
|
|
117
151
|
return socket.readyState === WebSocket.OPEN;
|
|
118
152
|
}
|
|
@@ -127,7 +161,7 @@ function createServerWsRpcClient(baseUrl: string): ServerWsRpcClient {
|
|
|
127
161
|
onErrorCallback = callback;
|
|
128
162
|
}
|
|
129
163
|
|
|
130
|
-
return { call, close, isOpen, onConnectionClose, onConnectionError, ready };
|
|
164
|
+
return { call, close, getConnection, isOpen, onConnectionClose, onConnectionError, ready };
|
|
131
165
|
}
|
|
132
166
|
|
|
133
167
|
export { createServerWsRpcClient };
|
package/shared/scripts.ts
CHANGED
|
@@ -7,38 +7,43 @@ import { fetchSchema } from "./utils/fetch_schema.js";
|
|
|
7
7
|
|
|
8
8
|
import opengeodeweb_front_schemas from "@geode/opengeodeweb-front/opengeodeweb_front_schemas.json" with { type: "json" };
|
|
9
9
|
|
|
10
|
-
function setAppBaseUrl(appBaseUrl: string) {
|
|
10
|
+
async function setAppBaseUrl(appBaseUrl: string): Promise<unknown> {
|
|
11
11
|
console.log("[API] setAppBaseUrl", appBaseUrl);
|
|
12
12
|
const schema = opengeodeweb_front_schemas.api.microservice.app.set_app_base_url;
|
|
13
13
|
const params = { baseUrl: appBaseUrl };
|
|
14
|
-
|
|
14
|
+
const result = await fetchSchema({ schema, params, baseURL: appBaseUrl });
|
|
15
|
+
return result;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
function setBackBaseUrl(appBaseUrl: string, backBaseUrl: string) {
|
|
18
|
+
async function setBackBaseUrl(appBaseUrl: string, backBaseUrl: string): Promise<unknown> {
|
|
18
19
|
console.log("[API] setBackBaseUrl", appBaseUrl, backBaseUrl);
|
|
19
20
|
const schema = opengeodeweb_front_schemas.api.microservice.app.set_back_base_url;
|
|
20
21
|
const params = { baseUrl: backBaseUrl };
|
|
21
|
-
|
|
22
|
+
const result = await fetchSchema({ schema, params, baseURL: appBaseUrl });
|
|
23
|
+
return result;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
function setViewerBaseUrl(appBaseUrl: string, viewerBaseUrl: string) {
|
|
26
|
+
async function setViewerBaseUrl(appBaseUrl: string, viewerBaseUrl: string): Promise<unknown> {
|
|
25
27
|
console.log("[API] setViewerBaseUrl", appBaseUrl, viewerBaseUrl);
|
|
26
28
|
const schema = opengeodeweb_front_schemas.api.microservice.app.set_viewer_base_url;
|
|
27
29
|
const params = { baseUrl: viewerBaseUrl };
|
|
28
|
-
|
|
30
|
+
const result = await fetchSchema({ schema, params, baseURL: appBaseUrl });
|
|
31
|
+
return result;
|
|
29
32
|
}
|
|
30
33
|
|
|
31
|
-
function setIsAppReady(appBaseUrl: string, isReady: boolean) {
|
|
34
|
+
async function setIsAppReady(appBaseUrl: string, isReady: boolean): Promise<unknown> {
|
|
32
35
|
console.log("[API] setIsAppReady", isReady);
|
|
33
36
|
const schema = opengeodeweb_front_schemas.api.microservice.app.set_is_app_ready;
|
|
34
37
|
const params = { isReady };
|
|
35
|
-
|
|
38
|
+
const result = await fetchSchema({ schema, params, baseURL: appBaseUrl });
|
|
39
|
+
return result;
|
|
36
40
|
}
|
|
37
41
|
|
|
38
|
-
function getIsAppReady(appBaseUrl: string) {
|
|
42
|
+
async function getIsAppReady(appBaseUrl: string): Promise<unknown> {
|
|
39
43
|
console.log("[API] getIsAppReady");
|
|
40
44
|
const schema = opengeodeweb_front_schemas.api.microservice.app.get_is_app_ready;
|
|
41
|
-
|
|
45
|
+
const result = await fetchSchema({ schema, baseURL: appBaseUrl });
|
|
46
|
+
return result;
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
export { getIsAppReady, setAppBaseUrl, setBackBaseUrl, setIsAppReady, setViewerBaseUrl };
|