@geode/opengeodeweb-front 10.5.1 → 10.6.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/app/components/FileUploader.vue +4 -5
- package/app/stores/app.js +80 -3
- package/app/stores/geode.js +54 -7
- package/app/stores/infra.js +25 -14
- package/app/stores/lambda.js +2 -1
- package/app/stores/viewer.js +40 -11
- package/app/utils/config.js +45 -0
- package/app/utils/extension.js +109 -0
- package/app/utils/local/microservices.js +259 -0
- package/app/utils/local/path.js +86 -0
- package/app/utils/local/scripts.js +49 -0
- package/app/utils/server.js +45 -0
- package/{app → internal}/utils/upload_file.js +8 -8
- package/nuxt.config.js +22 -4
- package/package.json +9 -4
- package/server/api/app/kill.post.js +11 -0
- package/server/api/app/project_folder_path.post.js +29 -0
- package/server/api/app/run_back.post.js +33 -0
- package/server/api/app/run_viewer.post.js +33 -0
- package/server/api/extensions/run.post.js +98 -0
- package/server/api/extensions/upload.put.js +105 -0
- package/tests/integration/microservices/back/requirements.txt +1 -1
- package/tests/integration/setup.js +39 -45
- package/tests/integration/stores/data_style/mesh/cells.nuxt.test.js +11 -22
- package/tests/integration/stores/data_style/mesh/edges.nuxt.test.js +10 -20
- package/tests/integration/stores/data_style/mesh/index.nuxt.test.js +10 -20
- package/tests/integration/stores/data_style/mesh/points.nuxt.test.js +10 -20
- package/tests/integration/stores/data_style/mesh/polygons.nuxt.test.js +10 -21
- package/tests/integration/stores/data_style/mesh/polyhedra.nuxt.test.js +10 -20
- package/tests/integration/stores/data_style/model/blocks.nuxt.test.js +10 -20
- package/tests/integration/stores/data_style/model/corners.nuxt.test.js +10 -20
- package/tests/integration/stores/data_style/model/edges.nuxt.test.js +10 -20
- package/tests/integration/stores/data_style/model/index.nuxt.test.js +10 -20
- package/tests/integration/stores/data_style/model/lines.nuxt.test.js +10 -16
- package/tests/integration/stores/data_style/model/points.nuxt.test.js +10 -15
- package/tests/integration/stores/data_style/model/surfaces.nuxt.test.js +15 -26
- package/tests/integration/stores/viewer.nuxt.test.js +6 -10
- package/tests/unit/composables/upload_file.nuxt.test.js +7 -9
- package/tests/unit/stores/infra.nuxt.test.js +6 -6
- package/tests/unit/stores/lambda.nuxt.test.js +2 -2
- package/app/utils/local.js +0 -361
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import DragAndDrop from "@ogw_front/components/DragAndDrop"
|
|
3
|
-
import
|
|
4
|
-
import { upload_file } from "@ogw_front/utils/upload_file"
|
|
5
|
-
|
|
6
|
-
const schema = schemas.opengeodeweb_back.upload_file
|
|
3
|
+
import { useGeodeStore } from "@ogw_front/stores/geode"
|
|
7
4
|
|
|
8
5
|
const emit = defineEmits(["files_uploaded", "decrement_step", "reset_values"])
|
|
9
6
|
|
|
@@ -15,6 +12,8 @@
|
|
|
15
12
|
mini: { type: Boolean, required: false, default: false },
|
|
16
13
|
})
|
|
17
14
|
|
|
15
|
+
const geodeStore = useGeodeStore()
|
|
16
|
+
|
|
18
17
|
const internal_files = ref(files)
|
|
19
18
|
const loading = ref(false)
|
|
20
19
|
const files_uploaded = ref(false)
|
|
@@ -40,7 +39,7 @@
|
|
|
40
39
|
async function upload_files() {
|
|
41
40
|
toggle_loading()
|
|
42
41
|
const promise_array = internal_files.value.map((file) =>
|
|
43
|
-
|
|
42
|
+
geodeStore.upload(file),
|
|
44
43
|
)
|
|
45
44
|
await Promise.all(promise_array)
|
|
46
45
|
files_uploaded.value = true
|
package/app/stores/app.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { upload_file } from "@ogw_internal/utils/upload_file.js"
|
|
2
|
+
import { api_fetch } from "@ogw_internal/utils/api_fetch.js"
|
|
3
|
+
|
|
1
4
|
export const useAppStore = defineStore("app", () => {
|
|
2
5
|
const stores = []
|
|
3
6
|
|
|
@@ -108,8 +111,7 @@ export const useAppStore = defineStore("app", () => {
|
|
|
108
111
|
})
|
|
109
112
|
finalURL = URL.createObjectURL(newBlob)
|
|
110
113
|
}
|
|
111
|
-
|
|
112
|
-
const extensionModule = await import(finalURL)
|
|
114
|
+
const extensionModule = await import(/* @vite-ignore */ finalURL)
|
|
113
115
|
|
|
114
116
|
if (finalURL !== path && finalURL.startsWith("blob:")) {
|
|
115
117
|
URL.revokeObjectURL(finalURL)
|
|
@@ -145,7 +147,6 @@ export const useAppStore = defineStore("app", () => {
|
|
|
145
147
|
loadedExtensions.value.set(extensionId, extensionData)
|
|
146
148
|
|
|
147
149
|
console.log(`[AppStore] Extension loaded successfully: ${extensionId}`)
|
|
148
|
-
|
|
149
150
|
return extensionModule
|
|
150
151
|
} else {
|
|
151
152
|
throw new Error("Extension must export an install function")
|
|
@@ -217,6 +218,76 @@ export const useAppStore = defineStore("app", () => {
|
|
|
217
218
|
return getExtension(id)?.enabled ?? false
|
|
218
219
|
}
|
|
219
220
|
|
|
221
|
+
function upload(file, callbacks = {}) {
|
|
222
|
+
const route = "/api/extensions/upload"
|
|
223
|
+
const store = useAppStore()
|
|
224
|
+
return upload_file(
|
|
225
|
+
store,
|
|
226
|
+
{ route, file },
|
|
227
|
+
{
|
|
228
|
+
...callbacks,
|
|
229
|
+
response_function: async (response) => {
|
|
230
|
+
console.log("[APP] Request completed:", route)
|
|
231
|
+
if (callbacks.response_function) {
|
|
232
|
+
await callbacks.response_function(response)
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function request(schema, params, callbacks = {}) {
|
|
240
|
+
console.log("[APP] Request:", schema.$id)
|
|
241
|
+
|
|
242
|
+
const store = useAppStore()
|
|
243
|
+
return api_fetch(
|
|
244
|
+
store,
|
|
245
|
+
{ schema, params },
|
|
246
|
+
{
|
|
247
|
+
...callbacks,
|
|
248
|
+
response_function: async (response) => {
|
|
249
|
+
console.log("[APP] Request completed:", schema.$id)
|
|
250
|
+
if (callbacks.response_function) {
|
|
251
|
+
await callbacks.response_function(response)
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const request_counter = ref(0)
|
|
259
|
+
function start_request() {
|
|
260
|
+
request_counter.value += 1
|
|
261
|
+
}
|
|
262
|
+
function stop_request() {
|
|
263
|
+
request_counter.value -= 1
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const projectFolderPath = ref("")
|
|
267
|
+
function createProjectFolder() {
|
|
268
|
+
const { PROJECT } = useRuntimeConfig().public
|
|
269
|
+
const schema = {
|
|
270
|
+
$id: "/api/app/project_folder_path",
|
|
271
|
+
methods: ["POST"],
|
|
272
|
+
type: "object",
|
|
273
|
+
properties: {
|
|
274
|
+
PROJECT: { type: "string" },
|
|
275
|
+
},
|
|
276
|
+
required: ["PROJECT"],
|
|
277
|
+
additionalProperties: true,
|
|
278
|
+
}
|
|
279
|
+
const params = { PROJECT }
|
|
280
|
+
|
|
281
|
+
console.log(createProjectFolder.name, { PROJECT })
|
|
282
|
+
|
|
283
|
+
return request(schema, params, {
|
|
284
|
+
response_function: async (response) => {
|
|
285
|
+
console.log(`[APP] ${response.projectFolderPath} created`)
|
|
286
|
+
projectFolderPath.value = response.projectFolderPath
|
|
287
|
+
},
|
|
288
|
+
})
|
|
289
|
+
}
|
|
290
|
+
|
|
220
291
|
return {
|
|
221
292
|
stores,
|
|
222
293
|
registerStore,
|
|
@@ -233,5 +304,11 @@ export const useAppStore = defineStore("app", () => {
|
|
|
233
304
|
toggleExtension,
|
|
234
305
|
setExtensionEnabled,
|
|
235
306
|
getExtensionEnabled,
|
|
307
|
+
request,
|
|
308
|
+
upload,
|
|
309
|
+
projectFolderPath,
|
|
310
|
+
createProjectFolder,
|
|
311
|
+
start_request,
|
|
312
|
+
stop_request,
|
|
236
313
|
}
|
|
237
314
|
})
|
package/app/stores/geode.js
CHANGED
|
@@ -4,6 +4,8 @@ import { appMode } from "@ogw_front/utils/app_mode"
|
|
|
4
4
|
import back_schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json"
|
|
5
5
|
import { useFeedbackStore } from "@ogw_front/stores/feedback"
|
|
6
6
|
import { useInfraStore } from "@ogw_front/stores/infra"
|
|
7
|
+
import { useAppStore } from "@ogw_front/stores/app"
|
|
8
|
+
import { upload_file } from "@ogw_internal/utils/upload_file.js"
|
|
7
9
|
|
|
8
10
|
const MILLISECONDS_IN_SECOND = 1000
|
|
9
11
|
const DEFAULT_PING_INTERVAL_SECONDS = 10
|
|
@@ -25,10 +27,6 @@ export const useGeodeStore = defineStore("geode", {
|
|
|
25
27
|
if (useInfraStore().app_mode === appMode.CLOUD) {
|
|
26
28
|
return "443"
|
|
27
29
|
}
|
|
28
|
-
const { GEODE_PORT } = useRuntimeConfig().public
|
|
29
|
-
if (GEODE_PORT !== null && GEODE_PORT !== "") {
|
|
30
|
-
return GEODE_PORT
|
|
31
|
-
}
|
|
32
30
|
return this.default_local_port
|
|
33
31
|
},
|
|
34
32
|
base_url() {
|
|
@@ -81,9 +79,39 @@ export const useGeodeStore = defineStore("geode", {
|
|
|
81
79
|
stop_request() {
|
|
82
80
|
this.request_counter -= 1
|
|
83
81
|
},
|
|
84
|
-
launch() {
|
|
85
|
-
console.log("[GEODE] Launching
|
|
86
|
-
|
|
82
|
+
launch(args) {
|
|
83
|
+
console.log("[GEODE] Launching back microservice...", { args })
|
|
84
|
+
const appStore = useAppStore()
|
|
85
|
+
|
|
86
|
+
const { BACK_PATH, BACK_COMMAND } = useRuntimeConfig().public
|
|
87
|
+
|
|
88
|
+
console.log("[GEODE] BACK_PATH", BACK_PATH)
|
|
89
|
+
console.log("[GEODE] BACK_COMMAND", BACK_COMMAND)
|
|
90
|
+
const schema = {
|
|
91
|
+
$id: "/api/app/run_back",
|
|
92
|
+
methods: ["POST"],
|
|
93
|
+
type: "object",
|
|
94
|
+
properties: {
|
|
95
|
+
BACK_PATH: { type: "string" },
|
|
96
|
+
BACK_COMMAND: { type: "string" },
|
|
97
|
+
},
|
|
98
|
+
required: ["BACK_PATH", "BACK_COMMAND"],
|
|
99
|
+
additionalProperties: true,
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const params = {
|
|
103
|
+
BACK_PATH,
|
|
104
|
+
BACK_COMMAND,
|
|
105
|
+
args,
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
console.log("[GEODE] params", params)
|
|
109
|
+
return appStore.request(schema, params, {
|
|
110
|
+
response_function: (response) => {
|
|
111
|
+
console.log(`[GEODE] Back launched on port ${response.port}`)
|
|
112
|
+
this.default_local_port = response.port
|
|
113
|
+
},
|
|
114
|
+
})
|
|
87
115
|
},
|
|
88
116
|
connect() {
|
|
89
117
|
console.log("[GEODE] Connecting to geode microservice...")
|
|
@@ -114,6 +142,25 @@ export const useGeodeStore = defineStore("geode", {
|
|
|
114
142
|
},
|
|
115
143
|
)
|
|
116
144
|
},
|
|
145
|
+
upload(file, callbacks = {}) {
|
|
146
|
+
const route = back_schemas.opengeodeweb_back.upload_file.$id
|
|
147
|
+
return upload_file(
|
|
148
|
+
this,
|
|
149
|
+
{
|
|
150
|
+
route,
|
|
151
|
+
file,
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
...callbacks,
|
|
155
|
+
response_function: async (response) => {
|
|
156
|
+
console.log("[GEODE] Request completed:", route)
|
|
157
|
+
if (callbacks.response_function) {
|
|
158
|
+
await callbacks.response_function(response)
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
)
|
|
163
|
+
},
|
|
117
164
|
},
|
|
118
165
|
share: {
|
|
119
166
|
omit: ["status"],
|
package/app/stores/infra.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { appMode, getAppMode } from "@ogw_front/utils/app_mode"
|
|
2
2
|
import { Status } from "@ogw_front/utils/status"
|
|
3
3
|
import { useLambdaStore } from "@ogw_front/stores/lambda"
|
|
4
|
+
import { useAppStore } from "@ogw_front/stores/app"
|
|
5
|
+
|
|
6
|
+
import { registerRunningExtensions } from "@ogw_front/utils/extension"
|
|
4
7
|
|
|
5
8
|
export const useInfraStore = defineStore("infra", {
|
|
6
9
|
state: () => ({
|
|
@@ -59,25 +62,33 @@ export const useInfraStore = defineStore("infra", {
|
|
|
59
62
|
}
|
|
60
63
|
console.log("[INFRA] Lock granted for create_backend")
|
|
61
64
|
|
|
62
|
-
if (this.app_mode === appMode.
|
|
63
|
-
console.log("[INFRA]
|
|
65
|
+
if (this.app_mode === appMode.CLOUD) {
|
|
66
|
+
console.log("[INFRA] CLOUD mode - Launching lambda...")
|
|
67
|
+
const lambdaStore = useLambdaStore()
|
|
68
|
+
this.ID = await lambdaStore.launch()
|
|
69
|
+
console.log("[INFRA] Lambda launched successfully")
|
|
70
|
+
} else {
|
|
71
|
+
console.log(
|
|
72
|
+
`[INFRA] ${this.app_mode} mode - Launching microservices...`,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
const appStore = useAppStore()
|
|
76
|
+
await appStore.createProjectFolder()
|
|
77
|
+
|
|
78
|
+
if (this.app_mode === appMode.DESKTOP) {
|
|
79
|
+
globalThis.electronAPI.project_folder_path({
|
|
80
|
+
projectFolderPath: appStore.projectFolderPath,
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
64
84
|
const microservices_with_launch = this.microservices.filter(
|
|
65
85
|
(store) => store.launch,
|
|
66
86
|
)
|
|
67
87
|
|
|
68
|
-
const
|
|
69
|
-
store.launch(),
|
|
88
|
+
const launch_promises = microservices_with_launch.map((store) =>
|
|
89
|
+
store.launch({ projectFolderPath: appStore.projectFolderPath }),
|
|
70
90
|
)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
for (const [index, store] of microservices_with_launch.entries()) {
|
|
74
|
-
store.$patch({ default_local_port: ports[index] })
|
|
75
|
-
}
|
|
76
|
-
} else if (this.app_mode === appMode.CLOUD) {
|
|
77
|
-
console.log("[INFRA] CLOUD mode - Launching lambda...")
|
|
78
|
-
const lambdaStore = useLambdaStore()
|
|
79
|
-
this.ID = await lambdaStore.launch()
|
|
80
|
-
console.log("[INFRA] Lambda launched successfully")
|
|
91
|
+
await Promise.all(launch_promises, registerRunningExtensions())
|
|
81
92
|
}
|
|
82
93
|
|
|
83
94
|
this.status = Status.CREATED
|
package/app/stores/lambda.js
CHANGED
|
@@ -15,7 +15,8 @@ export const useLambdaStore = defineStore("lambda", {
|
|
|
15
15
|
base_url() {
|
|
16
16
|
const public_runtime_config = useRuntimeConfig().public
|
|
17
17
|
const domain_name = public_runtime_config.API_URL
|
|
18
|
-
const
|
|
18
|
+
const projectPath = `/${public_runtime_config.PROJECT}`
|
|
19
|
+
const url = `${this.protocol}://${domain_name}:${this.port}${public_runtime_config.SITE_BRANCH}${projectPath}/createbackend`
|
|
19
20
|
return url
|
|
20
21
|
},
|
|
21
22
|
is_busy() {
|
package/app/stores/viewer.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// Third party imports
|
|
1
2
|
import vtkWSLinkClient, {
|
|
2
3
|
newInstance,
|
|
3
4
|
} from "@kitware/vtk.js/IO/Core/WSLinkClient"
|
|
@@ -5,9 +6,13 @@ import vtkWSLinkClient, {
|
|
|
5
6
|
import _ from "lodash"
|
|
6
7
|
// oxlint-disable-next-line no-unassigned-import
|
|
7
8
|
import "@kitware/vtk.js/Rendering/OpenGL/Profiles/Geometry"
|
|
9
|
+
import schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"
|
|
10
|
+
import { useRuntimeConfig } from "nuxt/app"
|
|
11
|
+
|
|
12
|
+
// Local imports
|
|
8
13
|
import { Status } from "@ogw_front/utils/status"
|
|
9
14
|
import { appMode } from "@ogw_front/utils/app_mode"
|
|
10
|
-
import
|
|
15
|
+
import { useAppStore } from "@ogw_front/stores/app"
|
|
11
16
|
import { useInfraStore } from "@ogw_front/stores/infra"
|
|
12
17
|
import { viewer_call } from "@ogw_internal/utils/viewer_call"
|
|
13
18
|
|
|
@@ -39,10 +44,6 @@ export const useViewerStore = defineStore(
|
|
|
39
44
|
if (infraStore.app_mode === appMode.CLOUD) {
|
|
40
45
|
return "443"
|
|
41
46
|
}
|
|
42
|
-
const { VIEWER_PORT } = useRuntimeConfig().public
|
|
43
|
-
if (VIEWER_PORT !== undefined && VIEWER_PORT !== "") {
|
|
44
|
-
return VIEWER_PORT
|
|
45
|
-
}
|
|
46
47
|
return default_local_port.value
|
|
47
48
|
})
|
|
48
49
|
|
|
@@ -149,12 +150,40 @@ export const useViewerStore = defineStore(
|
|
|
149
150
|
request_counter.value -= 1
|
|
150
151
|
}
|
|
151
152
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
153
|
+
function launch(args = { projectFolderPath }) {
|
|
154
|
+
console.log("[VIEWER] Launching viewer microservice...", { args })
|
|
155
|
+
const appStore = useAppStore()
|
|
156
|
+
|
|
157
|
+
const { VIEWER_PATH, VIEWER_COMMAND } = useRuntimeConfig().public
|
|
158
|
+
|
|
159
|
+
console.log("[VIEWER] VIEWER_PATH", VIEWER_PATH)
|
|
160
|
+
console.log("[VIEWER] VIEWER_COMMAND", VIEWER_COMMAND)
|
|
161
|
+
const schema = {
|
|
162
|
+
$id: "/api/app/run_viewer",
|
|
163
|
+
methods: ["POST"],
|
|
164
|
+
type: "object",
|
|
165
|
+
properties: {
|
|
166
|
+
VIEWER_PATH: { type: "string" },
|
|
167
|
+
VIEWER_COMMAND: { type: "string" },
|
|
168
|
+
},
|
|
169
|
+
required: ["VIEWER_PATH", "VIEWER_COMMAND"],
|
|
170
|
+
additionalProperties: true,
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const params = {
|
|
174
|
+
VIEWER_PATH,
|
|
175
|
+
VIEWER_COMMAND,
|
|
176
|
+
args,
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
console.log("[VIEWER] params", params)
|
|
180
|
+
|
|
181
|
+
return appStore.request(schema, params, {
|
|
182
|
+
response_function: (response) => {
|
|
183
|
+
console.log(`[VIEWER] Viewer launched on port ${response.port}`)
|
|
184
|
+
this.default_local_port = response.port
|
|
185
|
+
},
|
|
186
|
+
})
|
|
158
187
|
}
|
|
159
188
|
|
|
160
189
|
async function connect() {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Node.js imports
|
|
2
|
+
import path from "node:path"
|
|
3
|
+
|
|
4
|
+
// Third party imports
|
|
5
|
+
import Conf from "conf"
|
|
6
|
+
|
|
7
|
+
// Local imports
|
|
8
|
+
|
|
9
|
+
function projectConf(projectName) {
|
|
10
|
+
const projectConfig = new Conf({ projectName })
|
|
11
|
+
console.log(projectConf.name, { projectConfig })
|
|
12
|
+
return projectConfig
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function confFolderPath(projectName) {
|
|
16
|
+
const projectConfig = projectConf(projectName)
|
|
17
|
+
return path.dirname(projectConfig.path)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function extensionsConf(projectName) {
|
|
21
|
+
const projectConfig = projectConf(projectName)
|
|
22
|
+
if (!projectConfig.has("extensions")) {
|
|
23
|
+
projectConfig.set("extensions", {})
|
|
24
|
+
}
|
|
25
|
+
const extensionsConfig = projectConfig.get("extensions")
|
|
26
|
+
return extensionsConfig
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function addExtensionToConf(projectName, { extensionID, extensionPath }) {
|
|
30
|
+
const projectConfig = projectConf(projectName)
|
|
31
|
+
projectConfig.set(`extensions.${extensionID}.path`, extensionPath)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function extensionPathFromConf(projectName, extensionID) {
|
|
35
|
+
const projectConfig = projectConf(projectName)
|
|
36
|
+
return projectConfig.get(`extensions.${extensionID}.path`)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
confFolderPath,
|
|
41
|
+
projectConf,
|
|
42
|
+
extensionsConf,
|
|
43
|
+
addExtensionToConf,
|
|
44
|
+
extensionPathFromConf,
|
|
45
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// Node.js imports
|
|
2
|
+
|
|
3
|
+
// Third party imports
|
|
4
|
+
import _ from "lodash"
|
|
5
|
+
import { useRuntimeConfig } from "nuxt/app"
|
|
6
|
+
|
|
7
|
+
// Local imports
|
|
8
|
+
import { useAppStore } from "@ogw_front/stores/app"
|
|
9
|
+
import { useInfraStore } from "@ogw_front/stores/infra"
|
|
10
|
+
|
|
11
|
+
async function importExtensionFile(file) {
|
|
12
|
+
await uploadExtension(file)
|
|
13
|
+
return registerRunningExtensions()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function registerRunningExtensions() {
|
|
17
|
+
const appStore = useAppStore()
|
|
18
|
+
const infraStore = useInfraStore()
|
|
19
|
+
const { extensionsArray } = await runExtensions()
|
|
20
|
+
|
|
21
|
+
for (const extension of extensionsArray) {
|
|
22
|
+
const { id, name, version, frontendContent, port } = extension
|
|
23
|
+
const blob = new Blob([frontendContent], {
|
|
24
|
+
type: "application/javascript",
|
|
25
|
+
})
|
|
26
|
+
const blobUrl = URL.createObjectURL(blob)
|
|
27
|
+
const extensionModule = await appStore.loadExtension(blobUrl)
|
|
28
|
+
console.log("[ExtensionManager] Extension loaded:", id)
|
|
29
|
+
|
|
30
|
+
if (extensionModule.metadata?.store) {
|
|
31
|
+
const storeFactory = extensionModule.metadata.store
|
|
32
|
+
const store = storeFactory()
|
|
33
|
+
store.$patch((state) => {
|
|
34
|
+
state.default_local_port = port
|
|
35
|
+
})
|
|
36
|
+
appStore.registerStore(store)
|
|
37
|
+
console.log("[ExtensionManager] Store registered:", store.$id)
|
|
38
|
+
await store.connect()
|
|
39
|
+
console.log("[ExtensionManager] Microservice connected:", store.$id)
|
|
40
|
+
infraStore.register_microservice(store)
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
name,
|
|
44
|
+
version,
|
|
45
|
+
extensionModule,
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function unloadExtension(extensionId) {
|
|
51
|
+
const appStore = useAppStore()
|
|
52
|
+
console.log("[ExtensionManager] Unloading extension:", extensionId)
|
|
53
|
+
|
|
54
|
+
const extensionData = appStore.getExtension(extensionId)
|
|
55
|
+
if (!extensionData) {
|
|
56
|
+
console.warn("[ExtensionManager] Extension not found:", extensionId)
|
|
57
|
+
return false
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Get the store if it exists
|
|
61
|
+
const storeFactory = extensionData.metadata?.store
|
|
62
|
+
if (storeFactory) {
|
|
63
|
+
const store = storeFactory()
|
|
64
|
+
// Stop the microservice if possible
|
|
65
|
+
if (typeof store.kill === "function") {
|
|
66
|
+
await store.kill()
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Unload from AppStore
|
|
71
|
+
appStore.unloadExtension(extensionId)
|
|
72
|
+
|
|
73
|
+
console.log("[ExtensionManager] Extension unloaded:", extensionId)
|
|
74
|
+
return true
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function uploadExtension(file) {
|
|
78
|
+
const appStore = useAppStore()
|
|
79
|
+
await appStore.upload(file)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function runExtensions() {
|
|
83
|
+
const appStore = useAppStore()
|
|
84
|
+
const projectFolderPath = appStore.projectFolderPath
|
|
85
|
+
const { PROJECT: projectName } = useRuntimeConfig().public
|
|
86
|
+
const params = { projectFolderPath, projectName }
|
|
87
|
+
|
|
88
|
+
const schema = {
|
|
89
|
+
$id: "/api/extensions/run",
|
|
90
|
+
methods: ["POST"],
|
|
91
|
+
type: "object",
|
|
92
|
+
properties: {
|
|
93
|
+
projectFolderPath: { type: "string" },
|
|
94
|
+
projectName: { type: "string" },
|
|
95
|
+
},
|
|
96
|
+
required: ["projectFolderPath", "projectName"],
|
|
97
|
+
additionalProperties: false,
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return appStore.request(schema, params)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export {
|
|
104
|
+
importExtensionFile,
|
|
105
|
+
unloadExtension,
|
|
106
|
+
uploadExtension,
|
|
107
|
+
registerRunningExtensions,
|
|
108
|
+
runExtensions,
|
|
109
|
+
}
|