diff --git a/app/components/ObjectSelector.vue b/app/components/ObjectSelector.vue
index 616390ddc..812f75a92 100644
--- a/app/components/ObjectSelector.vue
+++ b/app/components/ObjectSelector.vue
@@ -1,6 +1,7 @@
-
-
+
+
@@ -139,7 +89,7 @@ await get_allowed_objects();
-
+
These files cannot be loaded together because they don't share a common data type.
diff --git a/app/stores/app.js b/app/stores/app.js
index 4051efe68..f4fb6d5c4 100644
--- a/app/stores/app.js
+++ b/app/stores/app.js
@@ -1,4 +1,5 @@
// Local imports
+import { getRestApiPort, getRestApiProtocol, isCloudMode } from "@ogw_front/utils/stores.js";
import { api_fetch } from "@ogw_internal/utils/api_fetch.js";
import { upload_file } from "@ogw_internal/utils/upload_file.js";
@@ -8,6 +9,20 @@ import { useInfraStore } from "@ogw_front/stores/infra";
// oxlint-disable-next-line max-lines-per-function, max-statements
export const useAppStore = defineStore("app", () => {
const stores = [];
+ const default_local_port = ref("3000");
+
+ const protocol = computed(() => getRestApiProtocol());
+
+ const port = computed(() => getRestApiPort(default_local_port.value));
+
+ const base_url = computed(() => {
+ const infraStore = useInfraStore();
+ let app_url = `${protocol.value}://${infraStore.domain_name}:${port.value}`;
+ if (isCloudMode()) {
+ app_url += `/server`;
+ }
+ return app_url;
+ });
function registerStore(store) {
const isAlreadyRegistered = stores.some((registeredStore) => registeredStore.$id === store.$id);
@@ -91,7 +106,7 @@ export const useAppStore = defineStore("app", () => {
return loadedExtensions.value.get(id);
}
- async function loadExtension(path, port, backendPath = undefined) {
+ async function loadExtension(path, extensionPort, backendPath = undefined) {
try {
let finalURL = path;
@@ -108,7 +123,7 @@ export const useAppStore = defineStore("app", () => {
// oxlint-disable-next-line no-inline-comments
const extensionModule = await import(/* @vite-ignore */ finalURL);
const store = extensionModule.metadata.store();
- store.$patch({ default_local_port: port });
+ store.$patch({ default_local_port: extensionPort });
if (finalURL !== path && finalURL.startsWith("blob:")) {
URL.revokeObjectURL(finalURL);
@@ -200,7 +215,7 @@ export const useAppStore = defineStore("app", () => {
const store = useAppStore();
return upload_file(
store,
- { route, file },
+ { schema, file },
{
...callbacks,
response_function: async (response) => {
@@ -214,16 +229,13 @@ export const useAppStore = defineStore("app", () => {
}
function request({ schema, params }, callbacks = {}) {
- console.log("[APP] Request:", schema.$id);
-
const store = useAppStore();
return api_fetch(
store,
- { schema, params, headers: {} },
+ { schema, params },
{
...callbacks,
response_function: async (response) => {
- console.log("[APP] Request completed:", schema.$id);
if (callbacks.response_function) {
await callbacks.response_function(response);
}
@@ -239,6 +251,7 @@ export const useAppStore = defineStore("app", () => {
function stop_request() {
request_counter.value -= 1;
}
+ const is_busy = computed(() => request_counter.value > 0);
const projectFolderPath = ref("");
function createProjectFolder() {
@@ -265,6 +278,7 @@ export const useAppStore = defineStore("app", () => {
return {
stores,
+ base_url,
registerStore,
exportStores,
importStores,
@@ -285,5 +299,6 @@ export const useAppStore = defineStore("app", () => {
createProjectFolder,
start_request,
stop_request,
+ is_busy,
};
});
diff --git a/app/stores/back.js b/app/stores/back.js
index e1a915422..a4034c13e 100644
--- a/app/stores/back.js
+++ b/app/stores/back.js
@@ -1,12 +1,13 @@
import { Status } from "@ogw_front/utils/status";
import { api_fetch } from "@ogw_internal/utils/api_fetch";
-import { appMode } from "@ogw_front/utils/local/app_mode";
import back_schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json";
import { upload_file } from "@ogw_internal/utils/upload_file.js";
import { useAppStore } from "@ogw_front/stores/app";
import { useFeedbackStore } from "@ogw_front/stores/feedback";
import { useInfraStore } from "@ogw_front/stores/infra";
+import { getRestApiPort, getRestApiProtocol, isCloudMode } from "@ogw_front/utils/stores";
+
const MILLISECONDS_IN_SECOND = 1000;
const DEFAULT_PING_INTERVAL_SECONDS = 10;
@@ -19,24 +20,18 @@ export const useBackStore = defineStore("back", {
}),
getters: {
protocol() {
- if (useInfraStore().app_mode === appMode.CLOUD) {
- return "https";
- }
- return "http";
+ return getRestApiProtocol();
},
port() {
- if (useInfraStore().app_mode === appMode.CLOUD) {
- return "443";
- }
- return this.default_local_port;
+ return getRestApiPort(this.default_local_port);
},
base_url() {
const infraStore = useInfraStore();
- let geode_url = `${this.protocol}://${infraStore.domain_name}:${this.port}`;
- if (infraStore.app_mode === appMode.CLOUD) {
- geode_url += `/geode`;
+ let back_url = `${this.protocol}://${infraStore.domain_name}:${this.port}`;
+ if (isCloudMode()) {
+ back_url += `/geode`;
}
- return geode_url;
+ return back_url;
},
is_busy() {
return this.request_counter > 0;
@@ -110,22 +105,12 @@ export const useBackStore = defineStore("back", {
return Promise.resolve();
},
request({ schema, params = {} }, callbacks = {}) {
- console.log("[GEODE] Request:", schema.$id);
- const start = Date.now();
-
return api_fetch(
this,
{ schema, params, headers: {} },
{
...callbacks,
response_function: async (response) => {
- console.log(
- "[GEODE] Request completed:",
- schema.$id,
- "in",
- (Date.now() - start) / MILLISECONDS_IN_SECOND,
- "s",
- );
if (callbacks.response_function) {
await callbacks.response_function(response);
}
@@ -134,17 +119,16 @@ export const useBackStore = defineStore("back", {
);
},
upload(file, callbacks = {}) {
- const route = back_schemas.opengeodeweb_back.upload_file.$id;
+ const schema = back_schemas.opengeodeweb_back.upload_file;
return upload_file(
this,
{
- route,
+ schema,
file,
},
{
...callbacks,
response_function: async (response) => {
- console.log("[GEODE] Request completed:", route);
if (callbacks.response_function) {
await callbacks.response_function(response);
}
diff --git a/app/stores/infra.js b/app/stores/infra.js
index 2fbdeffd8..ffff609eb 100644
--- a/app/stores/infra.js
+++ b/app/stores/infra.js
@@ -77,11 +77,6 @@ export const useInfraStore = defineStore("infra", {
},
async create_connection() {
console.log("[INFRA] Starting create_connection");
- console.log(
- "[INFRA] Connecting microservices:",
- this.microservices.map((store) => store.$id),
- );
-
await Promise.all(
this.microservices.map(async (store) => {
console.log("[INFRA] Connecting to microservice:", store.$id);
diff --git a/app/stores/viewer.js b/app/stores/viewer.js
index 51d702d1b..0aeb2ada6 100644
--- a/app/stores/viewer.js
+++ b/app/stores/viewer.js
@@ -9,11 +9,16 @@ import schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json
// Local imports
import { Status } from "@ogw_front/utils/status";
-import { appMode } from "@ogw_front/utils/local/app_mode";
import { useAppStore } from "@ogw_front/stores/app";
import { useInfraStore } from "@ogw_front/stores/infra";
import { viewer_call } from "@ogw_internal/utils/viewer_call";
+import {
+ getWebsocketApiPort,
+ getWebsocketApiProtocol,
+ isCloudMode,
+} from "@ogw_front/utils/stores.js";
+
const MS_PER_SECOND = 1000;
const SECONDS_PER_REQUEST = 10;
const request_timeout = MS_PER_SECOND * SECONDS_PER_REQUEST;
@@ -33,23 +38,13 @@ export const useViewerStore = defineStore(
const version = ref("0.0.0");
const busy = ref(0);
- const protocol = computed(() => {
- if (infraStore.app_mode === appMode.CLOUD) {
- return "wss";
- }
- return "ws";
- });
+ const protocol = computed(() => getWebsocketApiProtocol());
- const port = computed(() => {
- if (infraStore.app_mode === appMode.CLOUD) {
- return "443";
- }
- return default_local_port.value;
- });
+ const port = computed(() => getWebsocketApiPort(default_local_port.value));
const base_url = computed(() => {
let viewer_url = `${protocol.value}://${infraStore.domain_name}:${port.value}`;
- if (infraStore.app_mode === appMode.CLOUD) {
+ if (isCloudMode()) {
viewer_url += `/viewer`;
}
viewer_url += "/ws";
@@ -162,25 +157,13 @@ export const useViewerStore = defineStore(
}
function request({ schema, params = {}, timeout = request_timeout }, callbacks = {}) {
- console.log("[VIEWER] Request:", schema.$id);
- const start = Date.now();
-
- // Get current store instance to pass to viewer_call
const store = useViewerStore();
-
return viewer_call(
store,
{ schema, params, timeout },
{
...callbacks,
response_function: async (response) => {
- console.log(
- "[VIEWER] Request completed:",
- schema.$id,
- "in",
- (Date.now() - start) / MS_PER_SECOND,
- "s",
- );
if (callbacks.response_function) {
await callbacks.response_function(response);
}
diff --git a/app/utils/import_workflow.js b/app/utils/import_workflow.js
index 8631091ba..eb479a7d2 100644
--- a/app/utils/import_workflow.js
+++ b/app/utils/import_workflow.js
@@ -35,13 +35,6 @@ async function importWorkflow(files) {
return results;
}
-function buildImportItemFromPayloadApi(value, geode_object_type) {
- return {
- geode_object_type,
- ...value,
- };
-}
-
async function importItem(item) {
const dataStore = useDataStore();
const dataStyleStore = useDataStyleStore();
@@ -89,8 +82,7 @@ async function importFile(filename, geode_object_type) {
filename,
};
const response = await backStore.request({ schema, params });
- const item = buildImportItemFromPayloadApi(response, geode_object_type);
- return importItem(item);
+ return importItem(response);
}
async function importWorkflowFromSnapshot(items) {
diff --git a/app/utils/log.js b/app/utils/log.js
new file mode 100644
index 000000000..6fd4bf54a
--- /dev/null
+++ b/app/utils/log.js
@@ -0,0 +1,18 @@
+function startRequestLog(microservice, schema) {
+ console.log(`[${microservice.$id}] Request:`, schema.$id);
+ const requestStartingTime = new Date(Date.now());
+ return requestStartingTime;
+}
+
+function endRequestLog(microservice, schema, requestStartingTime) {
+ const requestEndingTime = new Date(Date.now());
+ console.log(
+ `[${microservice.$id}] Request completed:`,
+ schema.$id,
+ "in",
+ requestEndingTime.getSeconds() - requestStartingTime.getSeconds(),
+ "s",
+ );
+}
+
+export { startRequestLog, endRequestLog };
diff --git a/app/utils/stores.js b/app/utils/stores.js
new file mode 100644
index 000000000..eb4a92522
--- /dev/null
+++ b/app/utils/stores.js
@@ -0,0 +1,32 @@
+import { appMode } from "@ogw_front/utils/local/app_mode";
+import { useInfraStore } from "@ogw_front/stores/infra";
+
+function isCloudMode() {
+ const infraStore = useInfraStore();
+ return infraStore.app_mode === appMode.CLOUD;
+}
+
+function getRestApiProtocol() {
+ const protocol = isCloudMode() ? "https" : "http";
+ return protocol;
+}
+function getRestApiPort(defaultLocalPort) {
+ const port = isCloudMode() ? "443" : defaultLocalPort;
+ return port;
+}
+function getWebsocketApiProtocol() {
+ const protocol = isCloudMode() ? "wss" : "ws";
+ return protocol;
+}
+function getWebsocketApiPort(defaultLocalPort) {
+ const port = isCloudMode() ? "443" : defaultLocalPort;
+ return port;
+}
+
+export {
+ isCloudMode,
+ getRestApiPort,
+ getRestApiProtocol,
+ getWebsocketApiProtocol,
+ getWebsocketApiPort,
+};
diff --git a/internal/utils/api_fetch.js b/internal/utils/api_fetch.js
index 086e48cf3..a526ed500 100644
--- a/internal/utils/api_fetch.js
+++ b/internal/utils/api_fetch.js
@@ -1,78 +1,51 @@
-import _ from "lodash";
+import { endRequestLog, startRequestLog } from "@ogw_front/utils/log";
+import { fetchSchema } from "@ogw_shared/utils/fetch_schema";
import { useFeedbackStore } from "@ogw_front/stores/feedback";
-import { validate_schema } from "@ogw_front/utils/validate_schema";
-
-const ERROR_400 = 400;
export function api_fetch(
microservice,
- { schema, params, headers },
+ { schema, params = {}, headers = {} },
{ request_error_function, response_function, response_error_function, timeout } = {},
) {
const feedbackStore = useFeedbackStore();
-
- const body = params || {};
-
- const { valid, error: schema_error } = validate_schema(schema, body);
-
- if (!valid) {
- if (process.env.NODE_ENV !== "production") {
- console.log("Bad request", schema_error, schema, params);
- }
- feedbackStore.add_error(ERROR_400, schema.$id, "Bad request", schema_error);
- throw new Error(`${schema.$id}: ${schema_error}`);
- }
-
microservice.start_request();
- const method = schema.methods.find((methodItem) => methodItem !== "OPTIONS");
- const request_options = {
- method,
- headers,
- };
- if (!_.isEmpty(body)) {
- request_options.body = body;
- }
-
- if (schema.max_retry) {
- request_options.max_retry = schema.max_retry;
- }
-
- function performFetch() {
- return $fetch(schema.$id, {
+ const requestStartingTime = startRequestLog(microservice, schema);
+ return fetchSchema(
+ {
+ schema,
baseURL: microservice.base_url,
- ...request_options,
- onRequestError({ error }) {
+ params,
+ headers,
+ max_retry: schema.max_retry,
+ timeout,
+ },
+ {
+ onRequestError(error) {
microservice.stop_request();
feedbackStore.add_error(error.code, schema.$id, error.message, error.stack);
if (request_error_function) {
request_error_function(error);
}
},
- onResponse({ response }) {
- if (response.ok) {
- microservice.stop_request();
- if (response_function) {
- response_function(response._data);
- }
+ onResponse(data) {
+ endRequestLog(microservice, schema, requestStartingTime);
+ microservice.stop_request();
+ if (response_function) {
+ response_function(data);
}
},
- onResponseError({ response }) {
+ onResponseError(response) {
microservice.stop_request();
feedbackStore.add_error(response.status, schema.$id, response.name, response.description);
if (response_error_function) {
response_error_function(response);
}
},
- });
- }
-
- if (timeout > 0) {
- return pTimeout(performCall(), {
- milliseconds: timeout,
- message: `${schema.$id}: Timed out after ${timeout}ms`,
- });
- }
-
- return performFetch();
+ onValidationError(code, route, name, error) {
+ microservice.stop_request();
+ feedbackStore.add_error(code, route, name, error);
+ },
+ },
+ );
}
diff --git a/internal/utils/upload_file.js b/internal/utils/upload_file.js
index d98b07645..90e93e331 100644
--- a/internal/utils/upload_file.js
+++ b/internal/utils/upload_file.js
@@ -1,50 +1,54 @@
+import { fetchRaw } from "@ogw_shared/utils/fetch_raw.js";
import { useFeedbackStore } from "@ogw_front/stores/feedback.js";
-async function upload_file(
+function upload_file(
microservice,
- { route, file },
+ { schema, file },
{ request_error_function, response_function, response_error_function } = {},
) {
- console.log("[UPLOAD_FILE] Uploading file", { route, file });
+ console.log("[UPLOAD_FILE] Uploading file", { schema, file });
const feedbackStore = useFeedbackStore();
+
if (!(file instanceof File)) {
throw new Error("file must be a instance of File");
}
- const body = new FormData();
- body.append("file", file);
+ const params = new FormData();
+ params.append("file", file);
- const request_options = {
- method: "PUT",
- body,
- };
microservice.start_request();
- return await $fetch(route, {
- baseURL: microservice.base_url || "",
- ...request_options,
- onRequestError({ error }) {
- microservice.stop_request();
- feedbackStore.add_error(error.code, route, error.message, error.stack);
- if (request_error_function) {
- request_error_function(error);
- }
+ const route = schema.$id;
+
+ return fetchRaw(
+ {
+ route,
+ method: schema.methods.find((method) => method !== "OPTIONS"),
+ params,
+ baseURL: microservice.base_url,
},
- onResponse({ response }) {
- if (response.ok) {
+ {
+ onRequestError(error) {
+ microservice.stop_request();
+ feedbackStore.add_error(error.code, route, error.message, error.stack);
+ if (request_error_function) {
+ request_error_function(error);
+ }
+ },
+ onResponse(response) {
microservice.stop_request();
if (response_function) {
response_function(response);
}
- }
- },
- onResponseError({ response }) {
- microservice.stop_request();
- feedbackStore.add_error(response.status, route, response.name, response.description);
- if (response_error_function) {
- response_error_function(response);
- }
+ },
+ onResponseError(response) {
+ microservice.stop_request();
+ feedbackStore.add_error(response.status, route, response.name, response.description);
+ if (response_error_function) {
+ response_error_function(response);
+ }
+ },
},
- });
+ );
}
export { upload_file };
diff --git a/internal/utils/viewer_call.js b/internal/utils/viewer_call.js
index 127933f5a..d03a98484 100644
--- a/internal/utils/viewer_call.js
+++ b/internal/utils/viewer_call.js
@@ -1,6 +1,10 @@
+// Third party imports
import pTimeout from "p-timeout";
+
+// Local imports
+import { endRequestLog, startRequestLog } from "@ogw_front/utils/log";
import { useFeedbackStore } from "@ogw_front/stores/feedback";
-import { validate_schema } from "@ogw_front/utils/validate_schema";
+import { validate_schema } from "@ogw_shared/utils/validate_schema";
const ERROR_400 = 400;
@@ -28,9 +32,10 @@ export function viewer_call(
return;
}
microservice.start_request();
-
+ const requestStart = startRequestLog(microservice, schema);
try {
const value = await client.getConnection().getSession().call(schema.$id, [params]);
+ endRequestLog(microservice, schema, requestStart);
if (response_function) {
await response_function(value);
}
diff --git a/nuxt.config.js b/nuxt.config.js
index 3e6d32304..1142219a0 100644
--- a/nuxt.config.js
+++ b/nuxt.config.js
@@ -28,6 +28,7 @@ export default defineNuxtConfig({
"@ogw_front": path.resolve(__dirname, "app"),
"@ogw_internal": path.resolve(__dirname, "internal"),
"@ogw_server": path.resolve(__dirname, "server"),
+ "@ogw_shared": path.resolve(__dirname, "shared"),
"@ogw_tests": path.resolve(__dirname, "tests"),
},
diff --git a/shared/utils/fetch_raw.js b/shared/utils/fetch_raw.js
new file mode 100644
index 000000000..5686d9de5
--- /dev/null
+++ b/shared/utils/fetch_raw.js
@@ -0,0 +1,60 @@
+// Third party imports
+import _ from "lodash";
+import pTimeout from "p-timeout";
+
+// Local imports
+import { hasBody } from "./file.js";
+
+function fetchRaw(
+ { route, method, params = {}, baseURL, headers = {}, max_retry, timeout, expectEvent = false },
+ { onRequestError, onResponse, onResponseError } = {},
+) {
+ if (expectEvent) {
+ const value = "text/event-stream";
+ if (_.isEmpty(headers)) {
+ headers["Accept"] = value;
+ } else {
+ headers["Accept"] = `${headers["Accept"]}, ${value}`;
+ }
+ }
+
+ const request_options = { method, headers };
+ if (hasBody(params)) {
+ request_options.body = params;
+ }
+ if (max_retry) {
+ request_options.max_retry = max_retry;
+ }
+
+ function doFetch() {
+ return $fetch(route, {
+ baseURL,
+ ...request_options,
+ onRequestError({ error }) {
+ if (onRequestError) {
+ onRequestError(error);
+ }
+ },
+ onResponse({ response }) {
+ if (response.ok && onResponse) {
+ onResponse(response._data);
+ }
+ },
+ onResponseError({ response }) {
+ if (onResponseError) {
+ onResponseError(response);
+ }
+ },
+ });
+ }
+
+ if (timeout > 0) {
+ return pTimeout(doFetch(), {
+ milliseconds: timeout,
+ message: `${route}: Timed out after ${timeout}ms`,
+ });
+ }
+ return doFetch();
+}
+
+export { fetchRaw };
diff --git a/shared/utils/fetch_schema.js b/shared/utils/fetch_schema.js
new file mode 100644
index 000000000..165a8481f
--- /dev/null
+++ b/shared/utils/fetch_schema.js
@@ -0,0 +1,41 @@
+// Third party imports
+import { validate_schema } from "@geode/opengeodeweb-front/app/utils/validate_schema.js";
+
+// Local imports
+import { fetchRaw } from "./fetch_raw.js";
+
+const ERROR_400 = 400;
+
+function fetchSchema(
+ { schema, params = {}, baseURL, headers, timeout, expectEvent = false },
+ { onRequestError, onResponse, onResponseError, onValidationError } = {},
+) {
+ console.log("fetchSchema", { schema, baseURL, params, headers, timeout });
+ const { valid, error: schema_error } = validate_schema(schema, params);
+
+ if (!valid) {
+ if (process.env.NODE_ENV !== "production") {
+ console.log("Bad request", schema_error, schema, params);
+ }
+ if (onValidationError) {
+ onValidationError({ code: ERROR_400, name: "Bad request", error: schema_error });
+ }
+ throw new Error(`${schema.$id}: ${schema_error}`);
+ }
+
+ return fetchRaw(
+ {
+ route: schema.$id,
+ method: schema.methods.find((method) => method !== "OPTIONS"),
+ params,
+ baseURL,
+ headers,
+ max_retry: schema.max_retry,
+ timeout,
+ expectEvent,
+ },
+ { onRequestError, onResponse, onResponseError },
+ );
+}
+
+export { fetchSchema };
diff --git a/shared/utils/file.js b/shared/utils/file.js
new file mode 100644
index 000000000..0dcb993fd
--- /dev/null
+++ b/shared/utils/file.js
@@ -0,0 +1,15 @@
+import _ from "lodash";
+
+function assertFile(file) {
+ if (!(file instanceof File)) {
+ throw new Error("file must be an instance of File");
+ }
+}
+
+function hasBody(params) {
+ if (params instanceof FormData || params instanceof Blob) {
+ return true;
+ }
+ return !_.isEmpty(params);
+}
+export { assertFile, hasBody };
diff --git a/shared/utils/response_handlers/load.js b/shared/utils/response_handlers/load.js
new file mode 100644
index 000000000..94c12ef4e
--- /dev/null
+++ b/shared/utils/response_handlers/load.js
@@ -0,0 +1,74 @@
+function getFileExtension(filename) {
+ return filename.slice(filename.lastIndexOf(".") + 1);
+}
+
+function selectGeodeObject(objectMap) {
+ const objectKeys = Object.keys(objectMap);
+ if (objectKeys.length === 0) {
+ return undefined;
+ }
+ if (objectKeys.length === 1 && objectMap[objectKeys[0]].is_loadable > 0) {
+ return objectKeys[0];
+ }
+
+ const highestLoadScore = Math.max(...objectKeys.map((key) => objectMap[key].is_loadable));
+ if (highestLoadScore <= 0) {
+ return undefined;
+ }
+
+ const bestScoreObjects = objectKeys.filter(
+ (key) => objectMap[key].is_loadable === highestLoadScore,
+ );
+ if (bestScoreObjects.length === 1) {
+ return bestScoreObjects[0];
+ }
+
+ const highestPriority = Math.max(
+ ...bestScoreObjects.map((key) => objectMap[key].object_priority ?? -Infinity),
+ );
+ const bestPriorityObjects = bestScoreObjects.filter(
+ (key) => objectMap[key].object_priority === highestPriority,
+ );
+ if (highestPriority !== -Infinity && bestPriorityObjects.length === 1) {
+ return bestPriorityObjects[0];
+ }
+
+ return undefined;
+}
+
+function intersectAllowedObjects(allowedObjectsList) {
+ const allKeys = [...new Set(allowedObjectsList.flatMap((object) => Object.keys(object)))];
+ const commonKeys = allKeys.filter((key) => allowedObjectsList.every((object) => key in object));
+
+ const mergedAllowedObjects = {};
+ for (const key of commonKeys) {
+ const loadScores = allowedObjectsList.map((object) => object[key].is_loadable);
+ const priorities = allowedObjectsList
+ .map((object) => object[key].object_priority)
+ .filter((priority) => priority !== undefined);
+
+ mergedAllowedObjects[key] = { is_loadable: Math.min(...loadScores) };
+ if (priorities.length > 0) {
+ mergedAllowedObjects[key].object_priority = Math.max(...priorities);
+ }
+ }
+
+ return { commonKeys, allKeys, mergedAllowedObjects };
+}
+
+function resolveAllowedObjects(filenames, allowedObjectsList) {
+ const { commonKeys, allKeys, mergedAllowedObjects } = intersectAllowedObjects(allowedObjectsList);
+
+ const multipleFilesNoCommon =
+ filenames.length > 1 && allKeys.length > 0 && commonKeys.length === 0;
+
+ const selectedGeodeObject = selectGeodeObject(mergedAllowedObjects);
+
+ return {
+ mergedAllowedObjects,
+ multipleFilesNoCommon,
+ selectedGeodeObject,
+ };
+}
+
+export { resolveAllowedObjects, getFileExtension };
diff --git a/app/utils/validate_schema.js b/shared/utils/validate_schema.js
similarity index 100%
rename from app/utils/validate_schema.js
rename to shared/utils/validate_schema.js
diff --git a/tests/unit/utils/validate_schema.nuxt.test.js b/tests/unit/utils/validate_schema.nuxt.test.js
index dc5706f33..8fa29b267 100644
--- a/tests/unit/utils/validate_schema.nuxt.test.js
+++ b/tests/unit/utils/validate_schema.nuxt.test.js
@@ -2,7 +2,7 @@
import { describe, expect, test } from "vitest";
// Local imports
-import { validate_schema } from "@ogw_front/utils/validate_schema";
+import { validate_schema } from "@ogw_shared/utils/validate_schema";
// CONSTANTS
const MIN_0 = 0;