@geode/opengeodeweb-front 10.32.3-rc.1 → 10.33.0-rc.1
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/app/stores/viewer.js +5 -27
- package/internal/stores/data_style/mesh/points/common.js +6 -1
- package/internal/stores/data_style/mesh/points/visibility.js +3 -1
- package/internal/utils/api_fetch.js +1 -1
- package/internal/utils/viewer_call.js +37 -53
- package/internal/utils/ws_client.js +29 -0
- package/nuxt.config.js +24 -1
- package/package.json +1 -1
- package/server/utils/server_config.js +25 -0
- package/server/utils/ws_client.js +112 -0
- package/shared/utils/call_raw.js +46 -0
- package/shared/utils/call_schema.js +45 -0
- package/shared/utils/fetch_schema.js +7 -4
- package/shared/utils/parse_boolean.js +16 -0
- package/shared/utils/validate_schema.js +2 -2
- package/tests/unit/utils/validate_schema.nuxt.test.js +3 -3
package/app/stores/viewer.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
// Third party imports
|
|
2
|
-
import vtkWSLinkClient, { newInstance } from "@kitware/vtk.js/IO/Core/WSLinkClient";
|
|
3
2
|
import _ from "lodash";
|
|
4
3
|
// oxlint-disable-next-line no-unassigned-import
|
|
5
4
|
import "@kitware/vtk.js/Rendering/OpenGL/Profiles/Geometry";
|
|
6
|
-
import SmartConnect from "wslink/src/SmartConnect";
|
|
7
5
|
import { connectImageStream } from "@kitware/vtk.js/Rendering/Misc/RemoteView";
|
|
8
|
-
|
|
6
|
+
import { initWebSocketClient } from "@ogw_internal/utils/ws_client";
|
|
9
7
|
import opengeodeweb_front_schemas from "@geode/opengeodeweb-front/opengeodeweb_front_schemas.json" with { type: "json" };
|
|
10
8
|
import opengeodeweb_viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" with { type: "json" };
|
|
11
9
|
|
|
@@ -37,7 +35,6 @@ export const useViewerStore = defineStore(
|
|
|
37
35
|
const request_counter = ref(0);
|
|
38
36
|
const status = ref(Status.NOT_CONNECTED);
|
|
39
37
|
const version = ref("0.0.0");
|
|
40
|
-
const busy = ref(0);
|
|
41
38
|
|
|
42
39
|
const protocol = computed(() => getWebsocketApiProtocol());
|
|
43
40
|
|
|
@@ -77,29 +74,10 @@ export const useViewerStore = defineStore(
|
|
|
77
74
|
try {
|
|
78
75
|
console.log("VIEWER LOCK GRANTED !", lock);
|
|
79
76
|
status.value = Status.CONNECTING;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
client.value.onBusyChange((count) => {
|
|
87
|
-
busy.value = count;
|
|
88
|
-
});
|
|
89
|
-
client.value.onConnectionError((httpReq) => {
|
|
90
|
-
const message = httpReq?.response?.error || `Connection error`;
|
|
91
|
-
console.error(message);
|
|
92
|
-
});
|
|
93
|
-
client.value.onConnectionClose((httpReq) => {
|
|
94
|
-
const message = httpReq?.response?.error || `Connection close`;
|
|
95
|
-
status.value = Status.NOT_CONNECTED;
|
|
96
|
-
console.error(message);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
client.value.beginBusy();
|
|
100
|
-
await client.value.connect({
|
|
101
|
-
application: "Viewer",
|
|
102
|
-
sessionURL: base_url.value,
|
|
77
|
+
client.value = await initWebSocketClient(base_url.value, client.value, {
|
|
78
|
+
onConnectionClose: () => {
|
|
79
|
+
status.value = Status.NOT_CONNECTED;
|
|
80
|
+
},
|
|
103
81
|
});
|
|
104
82
|
connectImageStream(client.value.getConnection().getSession());
|
|
105
83
|
client.value.endBusy();
|
|
@@ -9,6 +9,10 @@ export function useMeshPointsCommonStyle() {
|
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
function mutateMeshPointsVisibility(response) {
|
|
13
|
+
return mutateMeshPointsStyle(response.id, { visibility: response.visibility });
|
|
14
|
+
}
|
|
15
|
+
|
|
12
16
|
function meshPointsStyle(id) {
|
|
13
17
|
return dataStyleState.getStyle(id).points;
|
|
14
18
|
}
|
|
@@ -26,7 +30,8 @@ export function useMeshPointsCommonStyle() {
|
|
|
26
30
|
return {
|
|
27
31
|
meshPointsStyle,
|
|
28
32
|
meshPointsColoring,
|
|
29
|
-
mutateMeshPointsStyle,
|
|
30
33
|
mutateMeshPointsColoring,
|
|
34
|
+
mutateMeshPointsStyle,
|
|
35
|
+
mutateMeshPointsVisibility,
|
|
31
36
|
};
|
|
32
37
|
}
|
|
@@ -23,7 +23,9 @@ export function useMeshPointsVisibilityStyle() {
|
|
|
23
23
|
params,
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
|
-
response_function
|
|
26
|
+
response_function(response) {
|
|
27
|
+
return meshPointsCommonStyle.mutateMeshPointsVisibility(response);
|
|
28
|
+
},
|
|
27
29
|
},
|
|
28
30
|
);
|
|
29
31
|
}
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
// Third party imports
|
|
2
|
-
import pTimeout from "p-timeout";
|
|
3
|
-
|
|
4
|
-
// Local imports
|
|
5
1
|
import { endRequestLog, startRequestLog } from "@ogw_front/utils/log";
|
|
2
|
+
import { callSchema } from "@ogw_shared/utils/call_schema";
|
|
6
3
|
import { useFeedbackStore } from "@ogw_front/stores/feedback";
|
|
7
|
-
import { validate_schema } from "@ogw_shared/utils/validate_schema";
|
|
8
|
-
|
|
9
|
-
const ERROR_400 = 400;
|
|
10
4
|
|
|
11
5
|
export function viewer_call(
|
|
12
6
|
microservice,
|
|
@@ -14,52 +8,42 @@ export function viewer_call(
|
|
|
14
8
|
{ request_error_function, response_function, response_error_function } = {},
|
|
15
9
|
) {
|
|
16
10
|
const feedbackStore = useFeedbackStore();
|
|
17
|
-
|
|
18
|
-
const { valid, error: schema_error } = validate_schema(schema, params);
|
|
19
|
-
|
|
20
|
-
if (!valid) {
|
|
21
|
-
if (process.env.NODE_ENV !== "production") {
|
|
22
|
-
console.log("Bad request", schema_error, schema, params);
|
|
23
|
-
}
|
|
24
|
-
feedbackStore.add_error(ERROR_400, schema.$id, "Bad request", schema_error);
|
|
25
|
-
throw new Error(`${schema.$id}: ${schema_error}`);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
11
|
const { client } = microservice;
|
|
29
12
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
13
|
+
const requestStartingTime = startRequestLog(microservice, schema);
|
|
14
|
+
return callSchema(
|
|
15
|
+
{
|
|
16
|
+
schema,
|
|
17
|
+
params,
|
|
18
|
+
client,
|
|
19
|
+
timeout,
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
request_error_function(error) {
|
|
23
|
+
microservice.stop_request();
|
|
24
|
+
feedbackStore.add_error(error.code, schema.$id, error.message, error.message);
|
|
25
|
+
if (request_error_function) {
|
|
26
|
+
request_error_function(error);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
response_function(data) {
|
|
30
|
+
endRequestLog(microservice, schema, requestStartingTime);
|
|
31
|
+
microservice.stop_request();
|
|
32
|
+
if (response_function) {
|
|
33
|
+
response_function(data);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
response_error_function(response) {
|
|
37
|
+
microservice.stop_request();
|
|
38
|
+
feedbackStore.add_error(error.code, schema.$id, error.message, error.message);
|
|
39
|
+
if (response_error_function) {
|
|
40
|
+
response_error_function(response);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
validation_error_function({ code, name, error }) {
|
|
44
|
+
microservice.stop_request();
|
|
45
|
+
feedbackStore.add_error(code, schema.$id, name, error);
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
);
|
|
65
49
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Third party imports
|
|
2
|
+
import vtkWSLinkClient, { newInstance } from "@kitware/vtk.js/IO/Core/WSLinkClient";
|
|
3
|
+
import SmartConnect from "wslink/src/SmartConnect";
|
|
4
|
+
import _ from "lodash";
|
|
5
|
+
|
|
6
|
+
async function initWebSocketClient(baseUrl, initialClient = {}, { onConnectionClose } = {}) {
|
|
7
|
+
vtkWSLinkClient.setSmartConnectClass(SmartConnect);
|
|
8
|
+
const client = _.isEmpty(initialClient) ? newInstance() : initialClient;
|
|
9
|
+
|
|
10
|
+
client.onConnectionError((httpReq) => {
|
|
11
|
+
const message = httpReq?.response?.error || `Connection error`;
|
|
12
|
+
console.error(message);
|
|
13
|
+
});
|
|
14
|
+
client.onConnectionClose((httpReq) => {
|
|
15
|
+
const message = httpReq?.response?.error || `Connection close`;
|
|
16
|
+
onConnectionClose();
|
|
17
|
+
console.error(message);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
client.beginBusy();
|
|
21
|
+
await client.connect({
|
|
22
|
+
application: "Viewer",
|
|
23
|
+
sessionURL: baseUrl,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return client;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { initWebSocketClient };
|
package/nuxt.config.js
CHANGED
|
@@ -62,13 +62,36 @@ export default defineNuxtConfig({
|
|
|
62
62
|
vite: {
|
|
63
63
|
optimizeDeps: {
|
|
64
64
|
include: [
|
|
65
|
+
"@kitware/vtk.js",
|
|
66
|
+
"@kitware/vtk.js/Common/Core/Math",
|
|
67
|
+
"@kitware/vtk.js/IO/Core/WSLinkClient",
|
|
68
|
+
"@kitware/vtk.js/IO/XML/XMLPolyDataReader",
|
|
69
|
+
"@kitware/vtk.js/Rendering/Core/Actor",
|
|
70
|
+
"@kitware/vtk.js/Rendering/Core/AnnotatedCubeActor",
|
|
71
|
+
"@kitware/vtk.js/Rendering/Core/ColorTransferFunction",
|
|
72
|
+
"@kitware/vtk.js/Rendering/Core/Mapper",
|
|
73
|
+
"@kitware/vtk.js/Rendering/Misc/GenericRenderWindow",
|
|
74
|
+
"@kitware/vtk.js/Rendering/Misc/RemoteView",
|
|
75
|
+
"@kitware/vtk.js/Rendering/OpenGL/Profiles/Geometry",
|
|
76
|
+
"@kitware/vtk.js/Widgets/Core/WidgetManager",
|
|
77
|
+
"@kitware/vtk.js/Widgets/Widgets3D/ImplicitPlaneWidget",
|
|
78
|
+
"@vue/devtools-core",
|
|
79
|
+
"@vue/devtools-kit",
|
|
65
80
|
"ajv",
|
|
66
|
-
"
|
|
81
|
+
"broadcast-channel",
|
|
82
|
+
"dexie",
|
|
67
83
|
"globalthis",
|
|
68
84
|
"h3",
|
|
69
85
|
"js-file-download",
|
|
70
86
|
"lodash",
|
|
87
|
+
"lodash/merge",
|
|
88
|
+
"p-timeout",
|
|
71
89
|
"seedrandom",
|
|
90
|
+
"spark-md5",
|
|
91
|
+
"uuid",
|
|
92
|
+
"wslink",
|
|
93
|
+
"wslink/src/SmartConnect",
|
|
94
|
+
"xmlbuilder2",
|
|
72
95
|
],
|
|
73
96
|
},
|
|
74
97
|
},
|
package/package.json
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createServerWsRpcClient } from "./ws_client.js";
|
|
2
|
+
|
|
1
3
|
const storage = new Map();
|
|
2
4
|
|
|
3
5
|
function getAppBaseUrl() {
|
|
@@ -25,13 +27,36 @@ function setIsAppReady(isAppReady) {
|
|
|
25
27
|
return storage.set("IS_APP_READY", isAppReady);
|
|
26
28
|
}
|
|
27
29
|
|
|
30
|
+
async function getViewerWebSocketClient() {
|
|
31
|
+
const viewerClient = storage.get("VIEWER_CLIENT") ?? undefined;
|
|
32
|
+
if (viewerClient?.isOpen()) {
|
|
33
|
+
return viewerClient;
|
|
34
|
+
}
|
|
35
|
+
const viewerBaseUrl = await getViewerBaseUrl();
|
|
36
|
+
return setViewerWebSocketClient(viewerBaseUrl);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function setViewerWebSocketClient(baseUrl) {
|
|
40
|
+
const client = createServerWsRpcClient(baseUrl);
|
|
41
|
+
client.onConnectionClose(() => {
|
|
42
|
+
if (viewerClient === client) {
|
|
43
|
+
viewerClient = undefined;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
await client.ready;
|
|
47
|
+
storage.set("VIEWER_CLIENT", client);
|
|
48
|
+
return client;
|
|
49
|
+
}
|
|
50
|
+
|
|
28
51
|
export {
|
|
29
52
|
getAppBaseUrl,
|
|
30
53
|
getBackBaseUrl,
|
|
31
54
|
getIsAppReady,
|
|
32
55
|
getViewerBaseUrl,
|
|
56
|
+
getViewerWebSocketClient,
|
|
33
57
|
setAppBaseUrl,
|
|
34
58
|
setBackBaseUrl,
|
|
35
59
|
setIsAppReady,
|
|
36
60
|
setViewerBaseUrl,
|
|
61
|
+
setViewerWebSocketClient,
|
|
37
62
|
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// Third party imports
|
|
2
|
+
import { WebSocket } from "ws";
|
|
3
|
+
import { v4 as uuidv4 } from "uuid";
|
|
4
|
+
|
|
5
|
+
// Local imports
|
|
6
|
+
|
|
7
|
+
const HELLO_ID = "system:hello";
|
|
8
|
+
const HELLO_SECRET = "wslink-secret";
|
|
9
|
+
|
|
10
|
+
//oxlint-disable-next-line max-lines-per-function
|
|
11
|
+
function createServerWsRpcClient(baseUrl) {
|
|
12
|
+
const socket = new WebSocket(baseUrl);
|
|
13
|
+
const pending = new Map();
|
|
14
|
+
let onCloseCallback = undefined;
|
|
15
|
+
let onErrorCallback = undefined;
|
|
16
|
+
|
|
17
|
+
//oxlint-disable-next-line promise/avoid-new
|
|
18
|
+
const ready = new Promise((resolve, reject) => {
|
|
19
|
+
socket.on("open", () => {
|
|
20
|
+
socket.send(
|
|
21
|
+
JSON.stringify({
|
|
22
|
+
id: HELLO_ID,
|
|
23
|
+
method: "wslink.hello",
|
|
24
|
+
args: [{ secret: HELLO_SECRET }],
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
socket.on("message", (raw) => {
|
|
30
|
+
console.log("RAW WS MESSAGE:", raw.toString());
|
|
31
|
+
let message = undefined;
|
|
32
|
+
try {
|
|
33
|
+
message = JSON.parse(raw.toString());
|
|
34
|
+
} catch {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (message.id === HELLO_ID) {
|
|
39
|
+
resolve();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (typeof message.id === "string" && message.id.startsWith("publish:")) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const entry = pending.get(message.id);
|
|
48
|
+
if (!entry) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
pending.delete(message.id);
|
|
52
|
+
if (message.error) {
|
|
53
|
+
entry.reject(new Error(message.error.message || "wslink RPC error"));
|
|
54
|
+
} else {
|
|
55
|
+
entry.resolve(message.result);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
socket.on("error", (error) => {
|
|
60
|
+
onErrorCallback?.(error);
|
|
61
|
+
reject(error);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
socket.on("close", () => {
|
|
65
|
+
onCloseCallback?.();
|
|
66
|
+
for (const { reject: rejectPending } of pending.values()) {
|
|
67
|
+
rejectPending(new Error("WebSocket closed"));
|
|
68
|
+
}
|
|
69
|
+
pending.clear();
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
async function call(rpc, params = {}) {
|
|
74
|
+
await ready;
|
|
75
|
+
const id = uuidv4();
|
|
76
|
+
//oxlint-disable-next-line promise/avoid-new
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
pending.set(id, { resolve, reject });
|
|
79
|
+
socket.send(
|
|
80
|
+
JSON.stringify({
|
|
81
|
+
wslink: "1.0",
|
|
82
|
+
id,
|
|
83
|
+
method: rpc,
|
|
84
|
+
args: [params],
|
|
85
|
+
kwargs: { stream: true },
|
|
86
|
+
}),
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function close() {
|
|
92
|
+
socket.close();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function isOpen() {
|
|
96
|
+
return socket.readyState === WebSocket.OPEN;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
//oxlint-disable-next-line promise/prefer-await-to-callbacks
|
|
100
|
+
function onConnectionClose(callback) {
|
|
101
|
+
onCloseCallback = callback;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
//oxlint-disable-next-line promise/prefer-await-to-callbacks
|
|
105
|
+
function onConnectionError(callback) {
|
|
106
|
+
onErrorCallback = callback;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return { call, close, isOpen, onConnectionClose, onConnectionError, ready };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export { createServerWsRpcClient };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Third party imports
|
|
2
|
+
import _ from "lodash";
|
|
3
|
+
import pTimeout from "p-timeout";
|
|
4
|
+
|
|
5
|
+
// Local imports
|
|
6
|
+
|
|
7
|
+
function callClient({ rpc, params = {}, client }) {
|
|
8
|
+
if (globalThis.window !== undefined) {
|
|
9
|
+
return client.getConnection().getSession().call(rpc, [params]);
|
|
10
|
+
}
|
|
11
|
+
return client.call(rpc, params);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function callRaw(
|
|
15
|
+
{ rpc, params = {}, client, timeout },
|
|
16
|
+
{ request_error_function, response_function, response_error_function } = {},
|
|
17
|
+
) {
|
|
18
|
+
async function performCall() {
|
|
19
|
+
try {
|
|
20
|
+
const response = await callClient({ rpc, params, client });
|
|
21
|
+
if (response_function) {
|
|
22
|
+
await response_function(response);
|
|
23
|
+
}
|
|
24
|
+
return response;
|
|
25
|
+
} catch (error) {
|
|
26
|
+
if (request_error_function) {
|
|
27
|
+
request_error_function(error);
|
|
28
|
+
}
|
|
29
|
+
if (response_error_function) {
|
|
30
|
+
response_error_function(error);
|
|
31
|
+
}
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (timeout > 0) {
|
|
37
|
+
return pTimeout(performCall(), {
|
|
38
|
+
milliseconds: timeout,
|
|
39
|
+
message: `${rpc}: Timed out after ${timeout}ms`,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return performCall();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { callRaw };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Third party imports
|
|
2
|
+
|
|
3
|
+
// Local imports
|
|
4
|
+
import { callRaw } from "./call_raw.js";
|
|
5
|
+
import { validateSchema } from "./validate_schema.js";
|
|
6
|
+
|
|
7
|
+
const ERROR_400 = 400;
|
|
8
|
+
|
|
9
|
+
function callSchema(
|
|
10
|
+
{ schema, params = {}, client, timeout },
|
|
11
|
+
{
|
|
12
|
+
request_error_function,
|
|
13
|
+
response_function,
|
|
14
|
+
response_error_function,
|
|
15
|
+
validation_error_function,
|
|
16
|
+
} = {},
|
|
17
|
+
) {
|
|
18
|
+
const { valid, error: schema_error } = validateSchema(schema, params);
|
|
19
|
+
|
|
20
|
+
if (!valid) {
|
|
21
|
+
if (process.env.NODE_ENV !== "production") {
|
|
22
|
+
console.log("Bad request", schema_error, schema, params);
|
|
23
|
+
}
|
|
24
|
+
if (validation_error_function) {
|
|
25
|
+
validation_error_function({ code: ERROR_400, name: "Bad request", error: schema_error });
|
|
26
|
+
}
|
|
27
|
+
throw new Error(`${schema.$id}: ${schema_error}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return callRaw(
|
|
31
|
+
{
|
|
32
|
+
rpc: schema.$id,
|
|
33
|
+
params,
|
|
34
|
+
client,
|
|
35
|
+
timeout,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
request_error_function,
|
|
39
|
+
response_function,
|
|
40
|
+
response_error_function,
|
|
41
|
+
},
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { callSchema };
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// Local imports
|
|
4
4
|
import { fetchRaw } from "./fetch_raw.js";
|
|
5
|
-
import {
|
|
5
|
+
import { validateSchema } from "./validate_schema.js";
|
|
6
6
|
|
|
7
7
|
const ERROR_400 = 400;
|
|
8
8
|
|
|
@@ -15,8 +15,7 @@ function fetchSchema(
|
|
|
15
15
|
validation_error_function,
|
|
16
16
|
} = {},
|
|
17
17
|
) {
|
|
18
|
-
|
|
19
|
-
const { valid, error: schema_error } = validate_schema(schema, params);
|
|
18
|
+
const { valid, error: schema_error } = validateSchema(schema, params);
|
|
20
19
|
|
|
21
20
|
if (!valid) {
|
|
22
21
|
if (process.env.NODE_ENV !== "production") {
|
|
@@ -39,7 +38,11 @@ function fetchSchema(
|
|
|
39
38
|
timeout,
|
|
40
39
|
expectEvent,
|
|
41
40
|
},
|
|
42
|
-
{
|
|
41
|
+
{
|
|
42
|
+
request_error_function,
|
|
43
|
+
response_function,
|
|
44
|
+
response_error_function,
|
|
45
|
+
},
|
|
43
46
|
);
|
|
44
47
|
}
|
|
45
48
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const TRUTHY_VALUES = new Set([true, 1, "1", "true", "yes"]);
|
|
2
|
+
const FALSY_VALUES = new Set([false, 0, "0", "false", "no"]);
|
|
3
|
+
|
|
4
|
+
function parseBoolean(value) {
|
|
5
|
+
const normalized = typeof value === "string" ? value.trim().toLowerCase() : value;
|
|
6
|
+
|
|
7
|
+
if (TRUTHY_VALUES.has(normalized)) {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
if (FALSY_VALUES.has(normalized)) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
throw new Error(`Cannot parse boolean from: ${value}`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { parseBoolean };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Ajv from "ajv";
|
|
2
2
|
|
|
3
|
-
function
|
|
3
|
+
function validateSchema(schema, body) {
|
|
4
4
|
const ajv = new Ajv();
|
|
5
5
|
const list_keywords = ["methods", "route", "max_retry", "rpc"];
|
|
6
6
|
for (const keyword of list_keywords) {
|
|
@@ -10,4 +10,4 @@ function validate_schema(schema, body) {
|
|
|
10
10
|
return { valid, error: ajv.errorsText() };
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export {
|
|
13
|
+
export { validateSchema };
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { describe, expect, test } from "vitest";
|
|
3
3
|
|
|
4
4
|
// Local imports
|
|
5
|
-
import {
|
|
5
|
+
import { validateSchema } from "@ogw_shared/utils/validate_schema";
|
|
6
6
|
|
|
7
7
|
// CONSTANTS
|
|
8
8
|
const MIN_0 = 0;
|
|
@@ -24,14 +24,14 @@ describe("validate schema", () => {
|
|
|
24
24
|
|
|
25
25
|
test("ajv wrong params", () => {
|
|
26
26
|
const params = {};
|
|
27
|
-
const { valid, error } =
|
|
27
|
+
const { valid, error } = validateSchema(schema, params);
|
|
28
28
|
expect(valid).toBe(false);
|
|
29
29
|
expect(error).toBe("data must have required property 'var_1'");
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
test("good params", () => {
|
|
33
33
|
const params = { var_1: "test", var_2: VAL_5 };
|
|
34
|
-
const { valid, error } =
|
|
34
|
+
const { valid, error } = validateSchema(schema, params);
|
|
35
35
|
expect(valid).toBe(true);
|
|
36
36
|
expect(error).toBe("No errors");
|
|
37
37
|
});
|