@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.
Files changed (41) hide show
  1. package/app/components/FileUploader.vue +4 -5
  2. package/app/stores/app.js +80 -3
  3. package/app/stores/geode.js +54 -7
  4. package/app/stores/infra.js +25 -14
  5. package/app/stores/lambda.js +2 -1
  6. package/app/stores/viewer.js +40 -11
  7. package/app/utils/config.js +45 -0
  8. package/app/utils/extension.js +109 -0
  9. package/app/utils/local/microservices.js +259 -0
  10. package/app/utils/local/path.js +86 -0
  11. package/app/utils/local/scripts.js +49 -0
  12. package/app/utils/server.js +45 -0
  13. package/{app → internal}/utils/upload_file.js +8 -8
  14. package/nuxt.config.js +22 -4
  15. package/package.json +9 -4
  16. package/server/api/app/kill.post.js +11 -0
  17. package/server/api/app/project_folder_path.post.js +29 -0
  18. package/server/api/app/run_back.post.js +33 -0
  19. package/server/api/app/run_viewer.post.js +33 -0
  20. package/server/api/extensions/run.post.js +98 -0
  21. package/server/api/extensions/upload.put.js +105 -0
  22. package/tests/integration/microservices/back/requirements.txt +1 -1
  23. package/tests/integration/setup.js +39 -45
  24. package/tests/integration/stores/data_style/mesh/cells.nuxt.test.js +11 -22
  25. package/tests/integration/stores/data_style/mesh/edges.nuxt.test.js +10 -20
  26. package/tests/integration/stores/data_style/mesh/index.nuxt.test.js +10 -20
  27. package/tests/integration/stores/data_style/mesh/points.nuxt.test.js +10 -20
  28. package/tests/integration/stores/data_style/mesh/polygons.nuxt.test.js +10 -21
  29. package/tests/integration/stores/data_style/mesh/polyhedra.nuxt.test.js +10 -20
  30. package/tests/integration/stores/data_style/model/blocks.nuxt.test.js +10 -20
  31. package/tests/integration/stores/data_style/model/corners.nuxt.test.js +10 -20
  32. package/tests/integration/stores/data_style/model/edges.nuxt.test.js +10 -20
  33. package/tests/integration/stores/data_style/model/index.nuxt.test.js +10 -20
  34. package/tests/integration/stores/data_style/model/lines.nuxt.test.js +10 -16
  35. package/tests/integration/stores/data_style/model/points.nuxt.test.js +10 -15
  36. package/tests/integration/stores/data_style/model/surfaces.nuxt.test.js +15 -26
  37. package/tests/integration/stores/viewer.nuxt.test.js +6 -10
  38. package/tests/unit/composables/upload_file.nuxt.test.js +7 -9
  39. package/tests/unit/stores/infra.nuxt.test.js +6 -6
  40. package/tests/unit/stores/lambda.nuxt.test.js +2 -2
  41. package/app/utils/local.js +0 -361
@@ -0,0 +1,259 @@
1
+ // Node imports
2
+ import child_process from "node:child_process"
3
+ import fs from "node:fs"
4
+ import path from "node:path"
5
+
6
+ // Third party imports
7
+ import { WebSocket } from "ws"
8
+ import { getPort } from "get-port-please"
9
+ import pTimeout from "p-timeout"
10
+ import back_schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json" with { type: "json" }
11
+
12
+ // Local imports
13
+ import {
14
+ deleteFolderRecursive,
15
+ executablePath,
16
+ executableName,
17
+ } from "./path.js"
18
+ import { commandExistsSync, waitForReady } from "./scripts.js"
19
+
20
+ const DEFAULT_TIMEOUT_SECONDS = 30
21
+ const MILLISECONDS_PER_SECOND = 1000
22
+
23
+ function getAvailablePort() {
24
+ return getPort({
25
+ host: "localhost",
26
+ random: true,
27
+ })
28
+ }
29
+
30
+ async function runScript(
31
+ execName,
32
+ execPath,
33
+ args,
34
+ expectedResponse,
35
+ timeoutSeconds = DEFAULT_TIMEOUT_SECONDS,
36
+ ) {
37
+ const command = commandExistsSync(execName)
38
+ ? execName
39
+ : path.join(await executablePath(execPath), executableName(execName))
40
+ console.log("runScript", command, args)
41
+ const child = child_process.spawn(command, args, {
42
+ encoding: "utf8",
43
+ shell: true,
44
+ })
45
+
46
+ child.stdout.on("data", (data) =>
47
+ console.log(`[${execName}] ${data.toString()}`),
48
+ )
49
+ child.stderr.on("data", (data) =>
50
+ console.log(`[${execName}] ${data.toString()}`),
51
+ )
52
+
53
+ child.on("error", async (error) => {
54
+ const electron = await import("electron")
55
+ electron.dialog.showMessageBox({
56
+ title: "Title",
57
+ type: "warning",
58
+ message: `Error occured.\r\n${error}`,
59
+ })
60
+ })
61
+
62
+ child.on("close", (code) =>
63
+ console.log(`[${execName}] exited with code ${code}`),
64
+ )
65
+ child.on("kill", () => {
66
+ console.log(`[${execName}] process killed`)
67
+ })
68
+ child.name = command.replace(/^.*[\\/]/, "")
69
+
70
+ try {
71
+ return await pTimeout(waitForReady(child, expectedResponse), {
72
+ milliseconds: timeoutSeconds * MILLISECONDS_PER_SECOND,
73
+ message: `Timed out after ${timeoutSeconds} seconds`,
74
+ })
75
+ } catch (error) {
76
+ child.kill()
77
+ throw error
78
+ }
79
+ }
80
+
81
+ async function runBack(execName, execPath, args = {}) {
82
+ const { projectFolderPath } = args
83
+ if (!projectFolderPath) {
84
+ throw new Error("projectFolderPath is required")
85
+ }
86
+ let { uploadFolderPath } = args
87
+ if (!uploadFolderPath) {
88
+ uploadFolderPath = path.join(projectFolderPath, "uploads")
89
+ }
90
+ const port = await getAvailablePort()
91
+ const backArgs = [
92
+ `--port ${port}`,
93
+ `--data_folder_path ${projectFolderPath}`,
94
+ `--upload_folder_path ${uploadFolderPath}`,
95
+ `--allowed_origin http://localhost:*`,
96
+ `--timeout ${0}`,
97
+ ]
98
+ if (process.env.NODE_ENV === "development" || !process.env.NODE_ENV) {
99
+ backArgs.push("--debug")
100
+ }
101
+ console.log("runBack", execName, execPath, backArgs)
102
+ await runScript(execName, execPath, backArgs, "Serving Flask app")
103
+ return port
104
+ }
105
+
106
+ async function runViewer(execName, execPath, args = {}) {
107
+ const { projectFolderPath } = args
108
+ if (!projectFolderPath) {
109
+ throw new Error("projectFolderPath is required")
110
+ }
111
+ const port = await getAvailablePort()
112
+ const viewerArgs = [
113
+ `--port ${port}`,
114
+ `--data_folder_path ${projectFolderPath}`,
115
+ `--timeout ${0}`,
116
+ ]
117
+ console.log("runViewer", execName, execPath, viewerArgs)
118
+ await runScript(execName, execPath, viewerArgs, "Starting factory")
119
+ return port
120
+ }
121
+
122
+ function killHttpMicroservice(microservice) {
123
+ console.log("killHttpMicroservice", { ...microservice })
124
+ const failMessage = `Failed to kill ${microservice.name}`
125
+ async function do_kill() {
126
+ try {
127
+ await fetch(microservice.url, {
128
+ method: microservice.method,
129
+ })
130
+ throw new Error(failMessage)
131
+ } catch (error) {
132
+ console.log(`${microservice.name} closed`, error)
133
+ }
134
+ }
135
+ return pTimeout(do_kill(), {
136
+ milliseconds: 5000,
137
+ message: failMessage,
138
+ })
139
+ }
140
+
141
+ function killWebsocketMicroservice(microservice) {
142
+ console.log("killWebsocketMicroservice", { ...microservice })
143
+ const failMessage = `Failed to kill ${microservice.name}`
144
+ const successMessage = `Disconnected from ${microservice.name} WebSocket server`
145
+ function do_kill() {
146
+ return new Promise((resolve) => {
147
+ const socket = new WebSocket(microservice.url)
148
+ socket.on("open", () => {
149
+ console.log("Connected to WebSocket server")
150
+ socket.send(
151
+ JSON.stringify({
152
+ id: "system:hello",
153
+ method: "wslink.hello",
154
+ args: [{ secret: "wslink-secret" }],
155
+ }),
156
+ )
157
+ })
158
+ socket.on("message", (data) => {
159
+ const message = data.toString()
160
+ console.log("Received from server:", message)
161
+ if (message.includes("hello")) {
162
+ socket.send(
163
+ JSON.stringify({
164
+ id: "application.exit",
165
+ method: "application.exit",
166
+ }),
167
+ )
168
+ console.log(successMessage)
169
+ socket.close()
170
+ resolve()
171
+ }
172
+ })
173
+ socket.on("close", () => {
174
+ console.log(successMessage)
175
+ resolve()
176
+ })
177
+ socket.on("error", (error) => {
178
+ console.error("WebSocket error:", error)
179
+ socket.close()
180
+ resolve()
181
+ })
182
+ })
183
+ }
184
+ return pTimeout(do_kill(), {
185
+ milliseconds: 5000,
186
+ message: failMessage,
187
+ })
188
+ }
189
+
190
+ function killMicroservice(microservice) {
191
+ if (microservice.type === "back") {
192
+ return killHttpMicroservice(microservice)
193
+ } else if (microservice.type === "viewer") {
194
+ return killWebsocketMicroservice(microservice)
195
+ } else {
196
+ throw new Error(`Unknown microservice type: ${microservice.type}`)
197
+ }
198
+ }
199
+
200
+ function killMicroservices(microservices) {
201
+ console.log("killMicroservices", { microservices })
202
+ return Promise.all(
203
+ microservices.map(
204
+ async (microservice) => await killMicroservice(microservice),
205
+ ),
206
+ )
207
+ }
208
+ function projectMicroservices(projectFolderPath) {
209
+ console.log("projectMicroservices", { projectFolderPath })
210
+ const filePath = microservicesMetadatasPath(projectFolderPath)
211
+
212
+ if (!fs.existsSync(filePath)) {
213
+ const microservicesMetadatas = { microservices: [] }
214
+ fs.writeFileSync(
215
+ filePath,
216
+ JSON.stringify(microservicesMetadatas, null, 2),
217
+ "utf-8",
218
+ )
219
+ }
220
+ const content = JSON.parse(fs.readFileSync(filePath, "utf-8"))
221
+ return content.microservices
222
+ }
223
+
224
+ async function cleanupBackend(projectFolderPath) {
225
+ const microservices = projectMicroservices(projectFolderPath)
226
+ await killMicroservices(microservices)
227
+ await deleteFolderRecursive(projectFolderPath)
228
+ }
229
+
230
+ function microservicesMetadatasPath(projectFolderPath) {
231
+ return path.join(projectFolderPath, "microservices.json")
232
+ }
233
+
234
+ function addMicroserviceMetadatas(projectFolderPath, serviceObj) {
235
+ const microservices = projectMicroservices(projectFolderPath)
236
+ if (serviceObj.type === "back") {
237
+ const schema = back_schemas.opengeodeweb_back.kill
238
+ serviceObj.url = `http://localhost:${serviceObj.port}/${schema.$id}`
239
+ serviceObj.method = schema.methods[0]
240
+ } else if (serviceObj.type === "viewer") {
241
+ serviceObj.url = `ws://localhost:${serviceObj.port}/ws`
242
+ }
243
+
244
+ microservices.push(serviceObj)
245
+ fs.writeFileSync(
246
+ microservicesMetadatasPath(projectFolderPath),
247
+ JSON.stringify({ microservices }, null, 2),
248
+ )
249
+ }
250
+
251
+ export {
252
+ addMicroserviceMetadatas,
253
+ cleanupBackend,
254
+ getAvailablePort,
255
+ killMicroservices,
256
+ projectMicroservices,
257
+ runBack,
258
+ runViewer,
259
+ }
@@ -0,0 +1,86 @@
1
+ // Node imports
2
+ import fs from "node:fs"
3
+ import os from "node:os"
4
+ import path from "node:path"
5
+ import { setTimeout } from "node:timers/promises"
6
+
7
+ // Third party imports
8
+ import isElectron from "is-electron"
9
+ import { rimraf } from "rimraf"
10
+ import { v4 as uuidv4 } from "uuid"
11
+
12
+ const MAX_DELETE_FOLDER_RETRIES = 5
13
+
14
+ function venvScriptPath(microservicePath) {
15
+ const venvPath = path.join(microservicePath, "venv")
16
+ let scriptPath = ""
17
+ if (process.platform === "win32") {
18
+ scriptPath = path.join(venvPath, "Scripts")
19
+ } else {
20
+ scriptPath = path.join(venvPath, "bin")
21
+ }
22
+ return scriptPath
23
+ }
24
+
25
+ async function executablePath(microservicePath) {
26
+ if (isElectron()) {
27
+ const electron = await import("electron")
28
+ if (electron.app.isPackaged) {
29
+ return process.resourcesPath
30
+ } else {
31
+ return venvScriptPath(microservicePath)
32
+ }
33
+ } else {
34
+ return venvScriptPath(microservicePath)
35
+ }
36
+ }
37
+
38
+ function executableName(name) {
39
+ if (process.platform === "win32") {
40
+ return `${name}.exe`
41
+ }
42
+ return name
43
+ }
44
+
45
+ function createPath(dirPath) {
46
+ if (!fs.existsSync(dirPath)) {
47
+ fs.mkdirSync(dirPath, { recursive: true })
48
+ console.log(`${dirPath} directory created successfully!`)
49
+ }
50
+ return dirPath
51
+ }
52
+
53
+ function generateProjectFolderPath(projectName) {
54
+ return path.join(os.tmpdir(), projectName.replace(/\//g, "_"), uuidv4())
55
+ }
56
+
57
+ async function deleteFolderRecursive(folderPath) {
58
+ if (!fs.existsSync(folderPath)) {
59
+ console.log(`Folder ${folderPath} does not exist.`)
60
+ return
61
+ }
62
+ for (let i = 0; i <= MAX_DELETE_FOLDER_RETRIES; i += 1) {
63
+ try {
64
+ console.log(`Deleting folder: ${folderPath}`)
65
+ // oxlint-disable-next-line no-await-in-loop
66
+ await rimraf(folderPath)
67
+ console.log(`Deleted folder: ${folderPath}`)
68
+ return
69
+ } catch (error) {
70
+ console.error(`Error deleting folder ${folderPath}:`, error)
71
+ // Wait before retrying
72
+ const MILLISECONDS_PER_RETRY = 1000
73
+ const DELAY = MILLISECONDS_PER_RETRY * (i + 1)
74
+ // oxlint-disable-next-line no-await-in-loop
75
+ await setTimeout(DELAY)
76
+ console.log("Retrying delete folder")
77
+ }
78
+ }
79
+ }
80
+ export {
81
+ createPath,
82
+ executablePath,
83
+ executableName,
84
+ deleteFolderRecursive,
85
+ generateProjectFolderPath,
86
+ }
@@ -0,0 +1,49 @@
1
+ // Node imports
2
+ import { on } from "node:events"
3
+ import child_process from "node:child_process"
4
+ import fs from "node:fs"
5
+ import path from "node:path"
6
+
7
+ function commandExistsSync(execName) {
8
+ const envPath = process.env.PATH || ""
9
+ return envPath.split(path.delimiter).some((dir) => {
10
+ const filePath = path.join(dir, execName)
11
+ return fs.existsSync(filePath) && fs.statSync(filePath).isFile()
12
+ })
13
+ }
14
+
15
+ async function waitForReady(child, expectedResponse) {
16
+ for await (const [data] of on(child.stdout, "data")) {
17
+ if (data.toString().includes(expectedResponse)) {
18
+ return child
19
+ }
20
+ }
21
+ throw new Error("Process closed before signal")
22
+ }
23
+
24
+ async function waitNuxt(nuxtProcess) {
25
+ for await (const [data] of on(nuxtProcess.stdout, "data")) {
26
+ const output = data.toString()
27
+ console.log("Nuxt:", output)
28
+ const portMatch = output.match(/Listening on http:\/\/\[::\]:(\d+)/)
29
+ if (portMatch) {
30
+ const [, nuxtPort] = portMatch
31
+
32
+ console.log("Nuxt listening on port", nuxtPort)
33
+ return nuxtPort
34
+ }
35
+ }
36
+ throw new Error("Nuxt process closed without accepting connections")
37
+ }
38
+
39
+ async function runBrowser(scriptName) {
40
+ process.env.BROWSER = true
41
+
42
+ const nuxtProcess = child_process.spawn("npm", ["run", scriptName], {
43
+ shell: true,
44
+ FORCE_COLOR: true,
45
+ })
46
+ return await waitNuxt(nuxtProcess)
47
+ }
48
+
49
+ export { runBrowser, waitForReady, commandExistsSync }
@@ -0,0 +1,45 @@
1
+ // Node imports
2
+ import fs from "node:fs"
3
+ import path from "node:path"
4
+
5
+ // Third party imports
6
+ import JSZip from "jszip"
7
+
8
+ async function unzipFile(
9
+ zipFilePath,
10
+ outputDir = zipFilePath.replace(/\.[^/.]+$/, ""), // Remove the file extension
11
+ ) {
12
+ console.log("Unzipping file...", zipFilePath, outputDir)
13
+ try {
14
+ const data = await fs.promises.readFile(zipFilePath)
15
+ const zip = await JSZip.loadAsync(data)
16
+ await fs.promises.mkdir(outputDir, { recursive: true })
17
+ const promises = []
18
+
19
+ zip.forEach((relativePath, zipEntry) => {
20
+ const outputPath = path.join(outputDir, relativePath)
21
+
22
+ if (zipEntry.dir) {
23
+ promises.push(fs.promises.mkdir(outputPath, { recursive: true }))
24
+ } else {
25
+ promises.push(
26
+ zipEntry.async("nodebuffer").then(async (content) => {
27
+ await fs.promises.mkdir(path.dirname(outputPath), {
28
+ recursive: true,
29
+ })
30
+ await fs.promises.writeFile(outputPath, content)
31
+ }),
32
+ )
33
+ }
34
+ })
35
+
36
+ await Promise.all(promises)
37
+ console.log("Extraction complete!")
38
+ return outputDir
39
+ } catch (error) {
40
+ console.error("Error unzipping file:", error)
41
+ throw error
42
+ }
43
+ }
44
+
45
+ export { unzipFile }
@@ -1,12 +1,12 @@
1
- import { useFeedbackStore } from "@ogw_front/stores/feedback"
2
- import { useGeodeStore } from "@ogw_front/stores/geode"
1
+ import { useFeedbackStore } from "@ogw_front/stores/feedback.js"
3
2
 
4
3
  async function upload_file(
4
+ microservice,
5
5
  { route, file },
6
6
  { request_error_function, response_function, response_error_function } = {},
7
7
  ) {
8
+ console.log("[UPLOAD_FILE] Uploading file", { route, file })
8
9
  const feedbackStore = useFeedbackStore()
9
- const geodeStore = useGeodeStore()
10
10
  if (!(file instanceof File)) {
11
11
  throw new Error("file must be a instance of File")
12
12
  }
@@ -18,12 +18,12 @@ async function upload_file(
18
18
  method: "PUT",
19
19
  body: body,
20
20
  }
21
- geodeStore.start_request()
21
+ microservice.start_request()
22
22
  return $fetch(route, {
23
- baseURL: geodeStore.base_url,
23
+ baseURL: microservice.base_url || "",
24
24
  ...request_options,
25
25
  onRequestError({ error }) {
26
- geodeStore.stop_request()
26
+ microservice.stop_request()
27
27
  feedbackStore.add_error(error.code, route, error.message, error.stack)
28
28
  if (request_error_function) {
29
29
  request_error_function(error)
@@ -31,14 +31,14 @@ async function upload_file(
31
31
  },
32
32
  onResponse({ response }) {
33
33
  if (response.ok) {
34
- geodeStore.stop_request()
34
+ microservice.stop_request()
35
35
  if (response_function) {
36
36
  response_function(response)
37
37
  }
38
38
  }
39
39
  },
40
40
  onResponseError({ response }) {
41
- geodeStore.stop_request()
41
+ microservice.stop_request()
42
42
  feedbackStore.add_error(
43
43
  response.status,
44
44
  route,
package/nuxt.config.js CHANGED
@@ -1,18 +1,36 @@
1
+ // Node imports
1
2
  import path, { dirname } from "node:path"
2
3
  import { fileURLToPath } from "node:url"
3
4
 
5
+ // Local imports
6
+ import package_json from "./package.json"
7
+
4
8
  const __dirname = dirname(fileURLToPath(import.meta.url))
5
9
 
6
10
  export default defineNuxtConfig({
7
11
  runtimeConfig: {
8
12
  public: {
9
13
  API_URL: "api.geode-solutions.com",
14
+ BACK_COMMAND: "opengeodeweb-back",
15
+ BACK_PATH: path.join(
16
+ __dirname,
17
+ "tests",
18
+ "integration",
19
+ "microservices",
20
+ "back",
21
+ ),
22
+ BROWSER: process.env.BROWSER ?? false,
23
+ PROJECT: package_json.name,
10
24
  SITE_BRANCH:
11
25
  process.env.NODE_ENV === "production" ? process.env.SITE_BRANCH : "",
12
- PROJECT: process.env.NODE_ENV === "production" ? process.env.PROJECT : "",
13
- BROWSER: process.env.BROWSER ?? false,
14
- GEODE_PORT: process.env.GEODE_PORT ?? undefined,
15
- VIEWER_PORT: process.env.VIEWER_PORT ?? undefined,
26
+ VIEWER_COMMAND: "opengeodeweb-viewer",
27
+ VIEWER_PATH: path.join(
28
+ __dirname,
29
+ "tests",
30
+ "integration",
31
+ "microservices",
32
+ "viewer",
33
+ ),
16
34
  },
17
35
  },
18
36
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geode/opengeodeweb-front",
3
- "version": "10.5.1",
3
+ "version": "10.6.0",
4
4
  "description": "OpenSource Vue/Nuxt/Pinia/Vuetify framework for web applications",
5
5
  "homepage": "https://github.com/Geode-solutions/OpenGeodeWeb-Front",
6
6
  "bugs": {
@@ -41,15 +41,20 @@
41
41
  "@vueuse/nuxt": "13.1.0",
42
42
  "@vueuse/rxjs": "^14.1.0",
43
43
  "ajv": "8.17.1",
44
+ "busboy": "1.6.0",
45
+ "conf": "15.1.0",
44
46
  "dexie": "4.2.1",
45
47
  "get-port-please": "3.2.0",
46
48
  "is-electron": "2.2.2",
47
49
  "js-file-download": "0.4.12",
50
+ "jszip": "3.10.1",
51
+ "node-stream-zip": "1.15.0",
48
52
  "nuxt": "4.2.2",
49
53
  "p-timeout": "7.0.1",
50
54
  "pinia": "3.0.4",
51
55
  "rimraf": "6.1.3",
52
56
  "rxjs": "7.8.2",
57
+ "sanitize-filename": "1.6.3",
53
58
  "sass": "1.87.0",
54
59
  "semver": "7.7.1",
55
60
  "uuid": "11.1.0",
@@ -62,7 +67,7 @@
62
67
  "devDependencies": {
63
68
  "@nuxt/test-utils": "3.21.0",
64
69
  "@pinia/testing": "1.0.3",
65
- "@vitejs/plugin-vue": "5.2.4",
70
+ "@vitejs/plugin-vue": "6.0.4",
66
71
  "@vue/test-utils": "2.4.6",
67
72
  "eslint": "9.26.0",
68
73
  "eslint-plugin-import": "2.31.0",
@@ -77,11 +82,11 @@
77
82
  "prettier": "3.3.3",
78
83
  "resize-observer-polyfill": "1.5.1",
79
84
  "unplugin-auto-import": "20.0.0",
80
- "vite": "6.3.5",
85
+ "vite": "7.3.1",
81
86
  "vite-plugin-vuetify": "2.1.1",
82
87
  "vitest": "4.0.15",
83
88
  "vitest-environment-nuxt": "1.0.1",
84
- "vitest-indexeddb": "^0.0.1"
89
+ "vitest-indexeddb": "0.0.1"
85
90
  },
86
91
  "peerDependencies": {
87
92
  "electron": "36.4.0"
@@ -0,0 +1,11 @@
1
+ // Node imports
2
+
3
+ // Third party imports
4
+ import { defineEventHandler } from "h3"
5
+
6
+ // Local imports
7
+
8
+ export default defineEventHandler(() => {
9
+ console.log("Killing node server process")
10
+ process.exit()
11
+ })
@@ -0,0 +1,29 @@
1
+ // Node imports
2
+
3
+ // Third party imports
4
+ import { createError, defineEventHandler, readBody } from "h3"
5
+
6
+ // Local imports
7
+ import {
8
+ createPath,
9
+ generateProjectFolderPath,
10
+ } from "@geode/opengeodeweb-front/app/utils/local/path.js"
11
+
12
+ export default defineEventHandler(async (event) => {
13
+ try {
14
+ const { PROJECT } = await readBody(event)
15
+ const projectFolderPath = generateProjectFolderPath(PROJECT)
16
+ await createPath(projectFolderPath)
17
+
18
+ return {
19
+ statusCode: 200,
20
+ projectFolderPath,
21
+ }
22
+ } catch (error) {
23
+ console.log(error)
24
+ throw createError({
25
+ statusCode: 500,
26
+ statusMessage: error.message,
27
+ })
28
+ }
29
+ })
@@ -0,0 +1,33 @@
1
+ // Node imports
2
+
3
+ // Third party imports
4
+ import { createError, defineEventHandler, readBody } from "h3"
5
+
6
+ // Local imports
7
+ import {
8
+ addMicroserviceMetadatas,
9
+ runBack,
10
+ } from "@geode/opengeodeweb-front/app/utils/local/microservices.js"
11
+
12
+ export default defineEventHandler(async (event) => {
13
+ try {
14
+ const { BACK_COMMAND, BACK_PATH, args } = await readBody(event)
15
+ const port = await runBack(BACK_COMMAND, BACK_PATH, args)
16
+ await addMicroserviceMetadatas(args.projectFolderPath, {
17
+ type: "back",
18
+ name: BACK_COMMAND,
19
+ port,
20
+ })
21
+
22
+ return {
23
+ statusCode: 200,
24
+ port,
25
+ }
26
+ } catch (error) {
27
+ console.log(error)
28
+ throw createError({
29
+ statusCode: 500,
30
+ statusMessage: error.message,
31
+ })
32
+ }
33
+ })
@@ -0,0 +1,33 @@
1
+ // Node imports
2
+
3
+ // Third party imports
4
+ import { createError, defineEventHandler, readBody } from "h3"
5
+
6
+ // Local imports
7
+ import {
8
+ addMicroserviceMetadatas,
9
+ runViewer,
10
+ } from "@geode/opengeodeweb-front/app/utils/local/microservices.js"
11
+
12
+ export default defineEventHandler(async (event) => {
13
+ try {
14
+ const { VIEWER_COMMAND, VIEWER_PATH, args } = await readBody(event)
15
+ const port = await runViewer(VIEWER_COMMAND, VIEWER_PATH, args)
16
+ await addMicroserviceMetadatas(args.projectFolderPath, {
17
+ type: "viewer",
18
+ name: VIEWER_COMMAND,
19
+ port,
20
+ })
21
+
22
+ return {
23
+ statusCode: 200,
24
+ port,
25
+ }
26
+ } catch (error) {
27
+ console.log(error)
28
+ throw createError({
29
+ statusCode: 500,
30
+ statusMessage: error.message,
31
+ })
32
+ }
33
+ })