@geode/opengeodeweb-front 10.35.0-rc.5 → 10.35.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/.build/server/utils/app_config.js +4 -3
- package/.build/server/utils/cleanup.js +17 -16
- package/.build/server/utils/cloud.js +2 -1
- package/.build/server/utils/microservices.js +12 -11
- package/.build/server/utils/path.js +12 -11
- package/.build/server/utils/scripts.js +12 -11
- package/.build/server/utils/server.js +4 -3
- package/.build/shared/scripts.js +6 -5
- package/.build/shared/utils/call_schema.js +2 -1
- package/.build/shared/utils/fetch_schema.js +2 -1
- package/.build/shared/utils/file.js +2 -1
- package/app/components/InfraConnected.vue +0 -1
- package/app/components/Viewer/ContextMenu/InfoCard.vue +2 -1
- package/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue +2 -1
- package/app/composables/hover_highlight.ts +3 -2
- package/app/composables/project_manager.ts +0 -1
- package/app/composables/run_function_when_microservices_connected.ts +0 -2
- package/app/composables/use_adaptive_styles.ts +2 -1
- package/app/composables/use_quick_colormap.ts +2 -1
- package/app/plugins/consola_plain_logs.client.ts +46 -0
- package/app/stores/api.ts +3 -2
- package/app/stores/app.ts +3 -1
- package/app/stores/app_helpers/extension.ts +8 -7
- package/app/stores/treeview.ts +3 -2
- package/app/utils/cloud.ts +4 -2
- package/app/utils/extension.ts +7 -6
- package/app/utils/import_workflow.ts +3 -2
- package/app/utils/log.ts +3 -2
- package/internal/utils/api_fetch.ts +2 -1
- package/internal/utils/upload_file.ts +2 -1
- package/internal/utils/ws_client.ts +3 -2
- package/nuxt.config.ts +2 -0
- package/package.json +5 -4
- package/server/api/cloud/extensions/run.post.ts +3 -2
- package/server/api/local/app/kill.post.ts +2 -1
- package/server/api/local/app/project_folder_path.post.ts +2 -1
- package/server/api/local/app/run_back.post.ts +2 -1
- package/server/api/local/app/run_viewer.post.ts +2 -1
- package/server/api/local/extensions/kill.post.ts +3 -2
- package/server/api/local/extensions/run.post.ts +2 -2
- package/server/api/microservice/app/get_is_app_ready.get.ts +3 -2
- package/server/api/microservice/app/set_app_base_url.post.ts +3 -2
- package/server/api/microservice/app/set_back_base_url.post.ts +2 -1
- package/server/api/microservice/app/set_is_app_ready.post.ts +3 -2
- package/server/api/microservice/app/set_viewer_base_url.post.ts +2 -1
- package/server/api/microservice/extensions/download.post.ts +3 -2
- package/server/utils/app_config.ts +4 -3
- package/server/utils/cleanup.ts +17 -16
- package/server/utils/cloud.ts +3 -1
- package/server/utils/extension.ts +4 -3
- package/server/utils/microservices.ts +12 -11
- package/server/utils/path.ts +12 -11
- package/server/utils/scripts.ts +12 -11
- package/server/utils/server.ts +4 -3
- package/shared/scripts.ts +6 -5
- package/shared/utils/call_schema.ts +2 -1
- package/shared/utils/fetch_schema.ts +3 -1
- package/shared/utils/file.ts +2 -1
|
@@ -5,6 +5,7 @@ import { unlink } from "node:fs/promises";
|
|
|
5
5
|
// Third party imports
|
|
6
6
|
import Conf from "conf";
|
|
7
7
|
import StreamZip from "node-stream-zip";
|
|
8
|
+
import { consola } from "consola";
|
|
8
9
|
import sanitize from "sanitize-filename";
|
|
9
10
|
|
|
10
11
|
// Local imports
|
|
@@ -17,7 +18,7 @@ function projectConf(projectName: string): Conf<ExtensionsConfigSchema> {
|
|
|
17
18
|
const projectConfig = new Conf<ExtensionsConfigSchema>({
|
|
18
19
|
projectName,
|
|
19
20
|
});
|
|
20
|
-
|
|
21
|
+
consola.debug(projectConf.name, {
|
|
21
22
|
projectConfig,
|
|
22
23
|
});
|
|
23
24
|
return projectConfig;
|
|
@@ -57,9 +58,9 @@ async function removeExtensionFromConf(projectName: string, extensionId: string)
|
|
|
57
58
|
const projectConfig = projectConf(projectName);
|
|
58
59
|
const extensionArchivePath = extensionPathFromConf(projectName, extensionId);
|
|
59
60
|
await unlink(extensionArchivePath);
|
|
60
|
-
|
|
61
|
+
consola.info(`${extensionArchivePath} was deleted`);
|
|
61
62
|
projectConfig.delete(`extensions.${extensionId}`);
|
|
62
|
-
|
|
63
|
+
consola.info(`${extensionId} was deleted from ${projectName} config`);
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
interface ExtensionMetadata {
|
package/server/utils/cleanup.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { setTimeout } from "node:timers/promises";
|
|
|
5
5
|
|
|
6
6
|
// Third party imports
|
|
7
7
|
import { WebSocket } from "ws";
|
|
8
|
+
import { consola } from "consola";
|
|
8
9
|
import pTimeout from "p-timeout";
|
|
9
10
|
import { rimraf } from "rimraf";
|
|
10
11
|
|
|
@@ -20,23 +21,23 @@ const MAX_DELETE_FOLDER_RETRIES = 5;
|
|
|
20
21
|
|
|
21
22
|
async function deleteFolderRecursive(folderPath: string): Promise<void> {
|
|
22
23
|
if (!fs.existsSync(folderPath)) {
|
|
23
|
-
|
|
24
|
+
consola.info(`Folder ${folderPath} does not exist.`);
|
|
24
25
|
return;
|
|
25
26
|
}
|
|
26
27
|
for (let i = 0; i <= MAX_DELETE_FOLDER_RETRIES; i += 1) {
|
|
27
28
|
try {
|
|
28
|
-
|
|
29
|
+
consola.info(`Deleting folder: ${folderPath}`);
|
|
29
30
|
// oxlint-disable-next-line no-await-in-loop
|
|
30
31
|
await rimraf(folderPath);
|
|
31
|
-
|
|
32
|
+
consola.info(`Deleted folder: ${folderPath}`);
|
|
32
33
|
return;
|
|
33
34
|
} catch (error) {
|
|
34
|
-
|
|
35
|
+
consola.error(`Error deleting folder ${folderPath}:`, error);
|
|
35
36
|
const MILLISECONDS_PER_RETRY = 1000;
|
|
36
37
|
const DELAY = MILLISECONDS_PER_RETRY * (i + 1);
|
|
37
38
|
// oxlint-disable-next-line no-await-in-loop
|
|
38
39
|
await setTimeout(DELAY);
|
|
39
|
-
|
|
40
|
+
consola.info("Retrying delete folder");
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
throw new Error(
|
|
@@ -54,7 +55,7 @@ function isErrorWithMessage(error: unknown): error is { message: string } {
|
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
async function killHttpMicroservice(microservice: Microservice): Promise<void> {
|
|
57
|
-
|
|
58
|
+
consola.debug("killHttpMicroservice", {
|
|
58
59
|
...microservice,
|
|
59
60
|
});
|
|
60
61
|
const failMessage = `Failed to kill ${microservice.name}`;
|
|
@@ -68,7 +69,7 @@ async function killHttpMicroservice(microservice: Microservice): Promise<void> {
|
|
|
68
69
|
});
|
|
69
70
|
} catch (error) {
|
|
70
71
|
const message = isErrorWithMessage(error) ? error.message : String(error);
|
|
71
|
-
|
|
72
|
+
consola.info(`Expected error during kill of ${microservice.name}:`, message);
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
await pTimeout(do_kill(), {
|
|
@@ -78,7 +79,7 @@ async function killHttpMicroservice(microservice: Microservice): Promise<void> {
|
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
async function killWebsocketMicroservice(microservice: Microservice): Promise<void> {
|
|
81
|
-
|
|
82
|
+
consola.debug("killWebsocketMicroservice", {
|
|
82
83
|
...microservice,
|
|
83
84
|
});
|
|
84
85
|
const failMessage = `Failed to kill ${microservice.name}`;
|
|
@@ -92,7 +93,7 @@ async function killWebsocketMicroservice(microservice: Microservice): Promise<vo
|
|
|
92
93
|
await new Promise<void>((resolve) => {
|
|
93
94
|
const socket = new WebSocket(socketUrl);
|
|
94
95
|
socket.on("open", () => {
|
|
95
|
-
|
|
96
|
+
consola.info("Connected to WebSocket server");
|
|
96
97
|
socket.send(
|
|
97
98
|
JSON.stringify({
|
|
98
99
|
id: "system:hello",
|
|
@@ -107,7 +108,7 @@ async function killWebsocketMicroservice(microservice: Microservice): Promise<vo
|
|
|
107
108
|
});
|
|
108
109
|
socket.on("message", (data: Buffer | string) => {
|
|
109
110
|
const message = data.toString();
|
|
110
|
-
|
|
111
|
+
consola.debug("Received from server:", message);
|
|
111
112
|
if (message.includes("hello")) {
|
|
112
113
|
socket.send(
|
|
113
114
|
JSON.stringify({
|
|
@@ -115,17 +116,17 @@ async function killWebsocketMicroservice(microservice: Microservice): Promise<vo
|
|
|
115
116
|
method: "application.exit",
|
|
116
117
|
}),
|
|
117
118
|
);
|
|
118
|
-
|
|
119
|
+
consola.info(successMessage);
|
|
119
120
|
socket.close();
|
|
120
121
|
resolve();
|
|
121
122
|
}
|
|
122
123
|
});
|
|
123
124
|
socket.on("close", () => {
|
|
124
|
-
|
|
125
|
+
consola.info(successMessage);
|
|
125
126
|
resolve();
|
|
126
127
|
});
|
|
127
128
|
socket.on("error", (error: Error) => {
|
|
128
|
-
|
|
129
|
+
consola.error("WebSocket error:", error);
|
|
129
130
|
socket.close();
|
|
130
131
|
resolve();
|
|
131
132
|
});
|
|
@@ -149,7 +150,7 @@ async function killMicroservice(microservice: Microservice): Promise<void> {
|
|
|
149
150
|
}
|
|
150
151
|
|
|
151
152
|
async function killMicroservices(microservices: readonly Microservice[]): Promise<Microservice[]> {
|
|
152
|
-
|
|
153
|
+
consola.debug("killMicroservices", {
|
|
153
154
|
microservices,
|
|
154
155
|
});
|
|
155
156
|
const results = await Promise.allSettled(
|
|
@@ -173,7 +174,7 @@ function isMicroservicesMetadatas(value: unknown): value is { microservices: Mic
|
|
|
173
174
|
}
|
|
174
175
|
|
|
175
176
|
function projectMicroservices(projectFolderPath: string): Microservice[] {
|
|
176
|
-
|
|
177
|
+
consola.debug("projectMicroservices", {
|
|
177
178
|
projectFolderPath,
|
|
178
179
|
});
|
|
179
180
|
const filePath = microservicesMetadatasPath(projectFolderPath);
|
|
@@ -192,7 +193,7 @@ function projectMicroservices(projectFolderPath: string): Microservice[] {
|
|
|
192
193
|
|
|
193
194
|
async function cleanupBackend(projectFolderPath: string): Promise<void> {
|
|
194
195
|
if (!fs.existsSync(projectFolderPath)) {
|
|
195
|
-
|
|
196
|
+
consola.info(`Folder ${projectFolderPath} does not exist. Skipping cleanup.`);
|
|
196
197
|
return;
|
|
197
198
|
}
|
|
198
199
|
const microservices = projectMicroservices(projectFolderPath);
|
package/server/utils/cloud.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { consola } from "consola";
|
|
2
|
+
|
|
1
3
|
// Node imports
|
|
2
4
|
import { execFileSync } from "node:child_process";
|
|
3
5
|
import fs from "node:fs";
|
|
@@ -29,7 +31,7 @@ stderr_logfile_maxbytes=0
|
|
|
29
31
|
execFileSync("supervisorctl", ["reread"]);
|
|
30
32
|
execFileSync("supervisorctl", ["update"]);
|
|
31
33
|
const stdout = execFileSync("supervisorctl", ["start", name]);
|
|
32
|
-
|
|
34
|
+
consola.info("addSupervisorProgram", stdout);
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
function buildLocationBlock(routePath: string, port: number): string {
|
|
@@ -4,6 +4,7 @@ import path from "node:path";
|
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
|
|
6
6
|
// Third party imports
|
|
7
|
+
import { consola } from "consola";
|
|
7
8
|
import { createError } from "h3";
|
|
8
9
|
|
|
9
10
|
// Local imports
|
|
@@ -41,7 +42,7 @@ async function readExtensionMetadata(unzippedExtensionPath: string): Promise<Ext
|
|
|
41
42
|
}
|
|
42
43
|
const metadata = result.data;
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
consola.debug("readExtensionMetadata", { metadata });
|
|
45
46
|
if (!metadata.frontendFile) {
|
|
46
47
|
throw createError({
|
|
47
48
|
statusCode: 400,
|
|
@@ -63,14 +64,14 @@ async function readExtensionFrontend(
|
|
|
63
64
|
frontendFile: string,
|
|
64
65
|
id: string,
|
|
65
66
|
): Promise<string> {
|
|
66
|
-
|
|
67
|
+
consola.debug("readExtensionFrontend", { id });
|
|
67
68
|
const frontendFilePath = await extensionFrontendPath(
|
|
68
69
|
unzippedExtensionPath,
|
|
69
70
|
frontendFile,
|
|
70
71
|
path.resolve(),
|
|
71
72
|
id,
|
|
72
73
|
);
|
|
73
|
-
|
|
74
|
+
consola.debug("readExtensionFrontend", { frontendFilePath });
|
|
74
75
|
return fs.readFile(frontendFilePath, "utf8");
|
|
75
76
|
}
|
|
76
77
|
|
|
@@ -5,6 +5,7 @@ import path from "node:path";
|
|
|
5
5
|
|
|
6
6
|
// Third party imports
|
|
7
7
|
import back_schemas from "@geode/opengeodeweb-back/opengeodeweb_back_schemas.json" with { type: "json" };
|
|
8
|
+
import { consola } from "consola";
|
|
8
9
|
|
|
9
10
|
// Local imports
|
|
10
11
|
import { type Microservice, microservicesMetadatasPath, projectMicroservices } from "./cleanup.js";
|
|
@@ -31,13 +32,13 @@ async function runScript(
|
|
|
31
32
|
timeoutSeconds = DEFAULT_TIMEOUT_SECONDS,
|
|
32
33
|
): Promise<NamedChildProcess> {
|
|
33
34
|
const command = executablePath(execPath, execName);
|
|
34
|
-
|
|
35
|
+
consola.debug("runScript", command, args);
|
|
35
36
|
const child = child_process.spawn(command, args, {
|
|
36
37
|
stdio: ["ignore", "pipe", "pipe"],
|
|
37
38
|
}) as NamedChildProcess;
|
|
38
39
|
child.name = command.replace(/^.*[\\/]/u, "");
|
|
39
40
|
child.on("spawn", () => {
|
|
40
|
-
|
|
41
|
+
consola.info(`[${child.name}] spawned, pid=${child.pid}`);
|
|
41
42
|
});
|
|
42
43
|
const controller = new AbortController();
|
|
43
44
|
const timer = setTimeout(() => {
|
|
@@ -98,16 +99,16 @@ async function runBack(
|
|
|
98
99
|
try {
|
|
99
100
|
port = await getAvailablePort();
|
|
100
101
|
const executableArgs = backArgs(args, port);
|
|
101
|
-
|
|
102
|
+
consola.debug("runBack", execPath, execName, executableArgs);
|
|
102
103
|
await runScript(execPath, execName, executableArgs, "Serving Flask app");
|
|
103
104
|
return port;
|
|
104
105
|
} catch (error) {
|
|
105
106
|
if (!isPortInUseError(error)) {
|
|
106
|
-
|
|
107
|
+
consola.error("runBack error", error);
|
|
107
108
|
throw error;
|
|
108
109
|
}
|
|
109
110
|
if (attempts <= MAX_PORT_RETRIES) {
|
|
110
|
-
|
|
111
|
+
consola.info("Retrying runBack on conflicting port", port);
|
|
111
112
|
const newPort = await runBack(execName, execPath, args, attempts + 1);
|
|
112
113
|
return newPort;
|
|
113
114
|
}
|
|
@@ -136,16 +137,16 @@ async function runViewer(
|
|
|
136
137
|
"--timeout",
|
|
137
138
|
"0",
|
|
138
139
|
];
|
|
139
|
-
|
|
140
|
+
consola.debug("runViewer", execPath, execName, viewerArgs);
|
|
140
141
|
await runScript(execPath, execName, viewerArgs, "Starting factory");
|
|
141
142
|
return port;
|
|
142
143
|
} catch (error) {
|
|
143
144
|
if (!isPortInUseError(error)) {
|
|
144
|
-
|
|
145
|
+
consola.error("runViewer error", error);
|
|
145
146
|
throw error;
|
|
146
147
|
}
|
|
147
148
|
if (attempts <= MAX_PORT_RETRIES) {
|
|
148
|
-
|
|
149
|
+
consola.info("Retrying runViewer on conflicting port", port);
|
|
149
150
|
const newPort = await runViewer(execName, execPath, args, attempts + 1);
|
|
150
151
|
return newPort;
|
|
151
152
|
}
|
|
@@ -165,17 +166,17 @@ async function runExtension(
|
|
|
165
166
|
port = await getAvailablePort();
|
|
166
167
|
const executableArgs = backArgs(args, port);
|
|
167
168
|
const command = executablePath(execPath, execName);
|
|
168
|
-
|
|
169
|
+
consola.debug("runExtension", execPath, execName, executableArgs);
|
|
169
170
|
addSupervisorProgram(extensionId, command, executableArgs);
|
|
170
171
|
addNginxLocation(extensionId, port);
|
|
171
172
|
return port;
|
|
172
173
|
} catch (error) {
|
|
173
174
|
if (!isPortInUseError(error)) {
|
|
174
|
-
|
|
175
|
+
consola.error("runExtension error", error);
|
|
175
176
|
throw error;
|
|
176
177
|
}
|
|
177
178
|
if (attempts <= MAX_PORT_RETRIES) {
|
|
178
|
-
|
|
179
|
+
consola.info("Retrying runExtension on conflicting port", port);
|
|
179
180
|
const newPort = await runExtension(extensionId, execName, execPath, args, attempts + 1);
|
|
180
181
|
return newPort;
|
|
181
182
|
}
|
package/server/utils/path.ts
CHANGED
|
@@ -5,6 +5,7 @@ import path from "node:path";
|
|
|
5
5
|
import { setTimeout } from "node:timers/promises";
|
|
6
6
|
|
|
7
7
|
// Third party imports
|
|
8
|
+
import { consola } from "consola";
|
|
8
9
|
import { v4 as uuidv4 } from "uuid";
|
|
9
10
|
|
|
10
11
|
// Local imports
|
|
@@ -25,15 +26,15 @@ function findExecutableInDir(
|
|
|
25
26
|
): string | undefined {
|
|
26
27
|
const oneFilePath = path.join(baseDir, osExecutableName);
|
|
27
28
|
if (fs.existsSync(oneFilePath) && fs.statSync(oneFilePath).isFile()) {
|
|
28
|
-
|
|
29
|
+
consola.info(`[executablePath] Found OneFile executable: ${oneFilePath}`);
|
|
29
30
|
return oneFilePath;
|
|
30
31
|
}
|
|
31
32
|
const oneDirPath = path.join(baseDir, execName, osExecutableName);
|
|
32
33
|
if (fs.existsSync(oneDirPath) && fs.statSync(oneDirPath).isFile()) {
|
|
33
|
-
|
|
34
|
+
consola.info(`[executablePath] Found OneDir executable: ${oneDirPath}`);
|
|
34
35
|
return oneDirPath;
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
consola.info(
|
|
37
38
|
`[executablePath] Executable not found in ${baseDir} (tried OneFile and OneDir): ${execName}`,
|
|
38
39
|
);
|
|
39
40
|
return undefined;
|
|
@@ -45,10 +46,10 @@ function executablePath(execPath: string, execName: string): string {
|
|
|
45
46
|
const mode = process.env.MODE;
|
|
46
47
|
const nodeEnv = process.env.NODE_ENV;
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
consola.debug("[executablePath]", { execPath, execName, mode, nodeEnv, resourcesPath });
|
|
49
50
|
|
|
50
51
|
if (commandExistsSync(osExecutableName)) {
|
|
51
|
-
|
|
52
|
+
consola.info(`[executablePath] Found executable in PATH: ${osExecutableName}`);
|
|
52
53
|
return osExecutableName;
|
|
53
54
|
}
|
|
54
55
|
|
|
@@ -76,7 +77,7 @@ function createPath(dirPath: string): string {
|
|
|
76
77
|
fs.mkdirSync(dirPath, {
|
|
77
78
|
recursive: true,
|
|
78
79
|
});
|
|
79
|
-
|
|
80
|
+
consola.info(`${dirPath} directory created successfully!`);
|
|
80
81
|
}
|
|
81
82
|
return dirPath;
|
|
82
83
|
}
|
|
@@ -96,7 +97,7 @@ async function lookForLocalExtensionDistPath(
|
|
|
96
97
|
if (!fs.existsSync(localExtensionDistPath)) {
|
|
97
98
|
return undefined;
|
|
98
99
|
}
|
|
99
|
-
|
|
100
|
+
consola.info(
|
|
100
101
|
`[extensionFrontendPath] Found existing folder: ${localExtensionDistPath}, deleting it...`,
|
|
101
102
|
);
|
|
102
103
|
fs.rmSync(localExtensionDistPath, {
|
|
@@ -110,10 +111,10 @@ async function lookForLocalExtensionDistPath(
|
|
|
110
111
|
const MILLISECONDS_PER_RETRY = 1000;
|
|
111
112
|
for (let i = 0; i <= MAX_DELETE_FOLDER_RETRIES; i += 1) {
|
|
112
113
|
if (fs.existsSync(rebuiltFilePath)) {
|
|
113
|
-
|
|
114
|
+
consola.info(`Found rebuilt file: ${rebuiltFilePath}`);
|
|
114
115
|
return rebuiltFilePath;
|
|
115
116
|
}
|
|
116
|
-
|
|
117
|
+
consola.info(`Waiting for rebuild... attempt ${i}/${MAX_DELETE_FOLDER_RETRIES}`);
|
|
117
118
|
// oxlint-disable-next-line no-await-in-loop
|
|
118
119
|
await setTimeout(MILLISECONDS_PER_RETRY);
|
|
119
120
|
}
|
|
@@ -125,7 +126,7 @@ async function extensionFrontendPath(
|
|
|
125
126
|
rootPath: string,
|
|
126
127
|
extensionId: string,
|
|
127
128
|
): Promise<string> {
|
|
128
|
-
|
|
129
|
+
consola.debug("[extensionFrontendPath]", {
|
|
129
130
|
unzippedExtensionPath,
|
|
130
131
|
frontendFile,
|
|
131
132
|
rootPath,
|
|
@@ -157,7 +158,7 @@ function extensionBackendPath(
|
|
|
157
158
|
unzippedExtensionPath,
|
|
158
159
|
executableName(backendExecutableName),
|
|
159
160
|
);
|
|
160
|
-
|
|
161
|
+
consola.debug("runExtensions", {
|
|
161
162
|
backendExecutablePath,
|
|
162
163
|
});
|
|
163
164
|
return backendExecutablePath;
|
package/server/utils/scripts.ts
CHANGED
|
@@ -7,6 +7,7 @@ import path from "node:path";
|
|
|
7
7
|
import readline from "node:readline";
|
|
8
8
|
|
|
9
9
|
// Third party imports
|
|
10
|
+
import { consola } from "consola";
|
|
10
11
|
import { getPort } from "get-port-please";
|
|
11
12
|
|
|
12
13
|
// Local imports
|
|
@@ -99,19 +100,19 @@ async function waitForReady(
|
|
|
99
100
|
function becomeReady(): void {
|
|
100
101
|
cleanup();
|
|
101
102
|
readlineStdout.on("line", (line) => {
|
|
102
|
-
|
|
103
|
+
consola.info(`[${child.name}] ${line}`);
|
|
103
104
|
});
|
|
104
105
|
readlineStderr.on("line", (line) => {
|
|
105
|
-
|
|
106
|
+
consola.info(`[${child.name}] ${line}`);
|
|
106
107
|
});
|
|
107
108
|
child.once("close", (code) => {
|
|
108
|
-
|
|
109
|
+
consola.info(`[${child.name}] exited with code ${code}`);
|
|
109
110
|
});
|
|
110
111
|
resolve(child);
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
onLine = (lineOutput): void => {
|
|
114
|
-
|
|
115
|
+
consola.info(`[${child.name}] ${lineOutput}`);
|
|
115
116
|
recordOutput(lineOutput);
|
|
116
117
|
if (lineOutput.includes(expectedResponse)) {
|
|
117
118
|
becomeReady();
|
|
@@ -119,7 +120,7 @@ async function waitForReady(
|
|
|
119
120
|
};
|
|
120
121
|
|
|
121
122
|
onErrLine = (line): void => {
|
|
122
|
-
|
|
123
|
+
consola.info(`[${child.name}] ${line}`);
|
|
123
124
|
recordOutput(line);
|
|
124
125
|
if (line.includes(expectedResponse)) {
|
|
125
126
|
becomeReady();
|
|
@@ -132,7 +133,7 @@ async function waitForReady(
|
|
|
132
133
|
};
|
|
133
134
|
|
|
134
135
|
onClose = (code): void => {
|
|
135
|
-
|
|
136
|
+
consola.info(`[${child.name}] exited with code ${code}`);
|
|
136
137
|
cleanup();
|
|
137
138
|
reject(
|
|
138
139
|
new Error(
|
|
@@ -160,20 +161,20 @@ async function waitNuxt(
|
|
|
160
161
|
nuxtProcess: child_process.ChildProcessWithoutNullStreams,
|
|
161
162
|
): Promise<string> {
|
|
162
163
|
nuxtProcess.stderr.on("data", (data: Buffer) => {
|
|
163
|
-
|
|
164
|
+
consola.info("Nuxt STDERR:", data.toString().trim());
|
|
164
165
|
});
|
|
165
166
|
nuxtProcess.on("close", (code) => {
|
|
166
|
-
|
|
167
|
+
consola.info(`Nuxt process closed with code ${code}`);
|
|
167
168
|
});
|
|
168
169
|
for await (const [data] of on(nuxtProcess.stdout, "data")) {
|
|
169
170
|
const output = String(data);
|
|
170
|
-
|
|
171
|
+
consola.info("Nuxt STDOUT:", output.trim());
|
|
171
172
|
const portMatch = /Listening on http:\/\/\[::\]:(?<port>\d+)/u.exec(output);
|
|
172
173
|
const port = portMatch?.groups?.port;
|
|
173
174
|
if (port !== undefined) {
|
|
174
|
-
|
|
175
|
+
consola.info("Nuxt listening on port", port);
|
|
175
176
|
nuxtProcess.stdout.on("data", (newData: Buffer) => {
|
|
176
|
-
|
|
177
|
+
consola.info("Nuxt STDOUT:", newData.toString().trim());
|
|
177
178
|
});
|
|
178
179
|
return port;
|
|
179
180
|
}
|
package/server/utils/server.ts
CHANGED
|
@@ -4,6 +4,7 @@ import path from "node:path";
|
|
|
4
4
|
|
|
5
5
|
// Third party imports
|
|
6
6
|
import JSZip from "jszip";
|
|
7
|
+
import { consola } from "consola";
|
|
7
8
|
import { extract as extractTar } from "tar";
|
|
8
9
|
|
|
9
10
|
const TAR_ARCHIVE_PATTERN = /\.(?<ext>tar\.gz|tgz|tar)$/u;
|
|
@@ -46,7 +47,7 @@ async function unzipFile(
|
|
|
46
47
|
zipFilePath: string,
|
|
47
48
|
outputDir: string = zipFilePath.replace(/\.[^/.]+$/u, ""),
|
|
48
49
|
): Promise<string> {
|
|
49
|
-
|
|
50
|
+
consola.info("Unzipping file...", zipFilePath, outputDir);
|
|
50
51
|
try {
|
|
51
52
|
await fs.promises.mkdir(outputDir, { recursive: true });
|
|
52
53
|
|
|
@@ -56,10 +57,10 @@ async function unzipFile(
|
|
|
56
57
|
await extractZipArchive(zipFilePath, outputDir);
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
consola.info("Extraction complete!");
|
|
60
61
|
return outputDir;
|
|
61
62
|
} catch (error) {
|
|
62
|
-
|
|
63
|
+
consola.error("Error unzipping file:", error);
|
|
63
64
|
throw error;
|
|
64
65
|
}
|
|
65
66
|
}
|
package/shared/scripts.ts
CHANGED
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
// Third party imports
|
|
4
4
|
|
|
5
5
|
// Local imports
|
|
6
|
+
import { consola } from "consola";
|
|
6
7
|
import { fetchSchema } from "./utils/fetch_schema.js";
|
|
7
8
|
|
|
8
9
|
import opengeodeweb_front_schemas from "@geode/opengeodeweb-front/opengeodeweb_front_schemas.json" with { type: "json" };
|
|
9
10
|
|
|
10
11
|
async function setAppBaseUrl(appBaseUrl: string): Promise<unknown> {
|
|
11
|
-
|
|
12
|
+
consola.info("[API] setAppBaseUrl", appBaseUrl);
|
|
12
13
|
const schema = opengeodeweb_front_schemas.api.microservice.app.set_app_base_url;
|
|
13
14
|
const params = { baseUrl: appBaseUrl };
|
|
14
15
|
const result = await fetchSchema({ schema, params, baseURL: appBaseUrl });
|
|
@@ -16,7 +17,7 @@ async function setAppBaseUrl(appBaseUrl: string): Promise<unknown> {
|
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
async function setBackBaseUrl(appBaseUrl: string, backBaseUrl: string): Promise<unknown> {
|
|
19
|
-
|
|
20
|
+
consola.info("[API] setBackBaseUrl", appBaseUrl, backBaseUrl);
|
|
20
21
|
const schema = opengeodeweb_front_schemas.api.microservice.app.set_back_base_url;
|
|
21
22
|
const params = { baseUrl: backBaseUrl };
|
|
22
23
|
const result = await fetchSchema({ schema, params, baseURL: appBaseUrl });
|
|
@@ -24,7 +25,7 @@ async function setBackBaseUrl(appBaseUrl: string, backBaseUrl: string): Promise<
|
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
async function setViewerBaseUrl(appBaseUrl: string, viewerBaseUrl: string): Promise<unknown> {
|
|
27
|
-
|
|
28
|
+
consola.info("[API] setViewerBaseUrl", appBaseUrl, viewerBaseUrl);
|
|
28
29
|
const schema = opengeodeweb_front_schemas.api.microservice.app.set_viewer_base_url;
|
|
29
30
|
const params = { baseUrl: viewerBaseUrl };
|
|
30
31
|
const result = await fetchSchema({ schema, params, baseURL: appBaseUrl });
|
|
@@ -32,7 +33,7 @@ async function setViewerBaseUrl(appBaseUrl: string, viewerBaseUrl: string): Prom
|
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
async function setIsAppReady(appBaseUrl: string, isReady: boolean): Promise<unknown> {
|
|
35
|
-
|
|
36
|
+
consola.info("[API] setIsAppReady", isReady);
|
|
36
37
|
const schema = opengeodeweb_front_schemas.api.microservice.app.set_is_app_ready;
|
|
37
38
|
const params = { isReady };
|
|
38
39
|
const result = await fetchSchema({ schema, params, baseURL: appBaseUrl });
|
|
@@ -40,7 +41,7 @@ async function setIsAppReady(appBaseUrl: string, isReady: boolean): Promise<unkn
|
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
async function getIsAppReady(appBaseUrl: string): Promise<unknown> {
|
|
43
|
-
|
|
44
|
+
consola.info("[API] getIsAppReady");
|
|
44
45
|
const schema = opengeodeweb_front_schemas.api.microservice.app.get_is_app_ready;
|
|
45
46
|
const result = await fetchSchema({ schema, baseURL: appBaseUrl });
|
|
46
47
|
return result;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// Local imports
|
|
4
4
|
import type { JsonRpcSchema, RequestHandlersWithValidation } from "./types.js";
|
|
5
5
|
import { type RpcClient, callRaw } from "./call_raw.js";
|
|
6
|
+
import { consola } from "consola";
|
|
6
7
|
import { validateSchema } from "./validate_schema.js";
|
|
7
8
|
|
|
8
9
|
const ERROR_400 = 400;
|
|
@@ -27,7 +28,7 @@ async function callSchema(
|
|
|
27
28
|
|
|
28
29
|
if (!valid) {
|
|
29
30
|
if (process.env.NODE_ENV !== "production") {
|
|
30
|
-
|
|
31
|
+
consola.error("Bad request", schema_error, schema, params);
|
|
31
32
|
}
|
|
32
33
|
if (validation_error_function) {
|
|
33
34
|
validation_error_function({ code: ERROR_400, name: "Bad request", error: schema_error });
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { consola } from "consola";
|
|
2
|
+
|
|
1
3
|
// Local imports
|
|
2
4
|
import type { JsonRpcSchema, RequestHandlersWithValidation } from "./types.js";
|
|
3
5
|
import { fetchRaw } from "./fetch_raw.js";
|
|
@@ -27,7 +29,7 @@ async function fetchSchema(
|
|
|
27
29
|
|
|
28
30
|
if (!valid) {
|
|
29
31
|
if (process.env.NODE_ENV !== "production") {
|
|
30
|
-
|
|
32
|
+
consola.error("Bad request", schema_error, schema, params);
|
|
31
33
|
}
|
|
32
34
|
if (validation_error_function) {
|
|
33
35
|
validation_error_function({ code: ERROR_400, name: "Bad request", error: schema_error });
|
package/shared/utils/file.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import _ from "lodash";
|
|
2
|
+
import { consola } from "consola";
|
|
2
3
|
|
|
3
4
|
const BYTES_PER_KIBIBYTE = 1024;
|
|
4
5
|
const KIBIBYTES_PER_MEBIBYTE = 1024;
|
|
@@ -7,7 +8,7 @@ const CHUNK_SIZE_MEBIBYTES = 8;
|
|
|
7
8
|
const CHUNK_SIZE_BYTES = CHUNK_SIZE_MEBIBYTES * KIBIBYTES_PER_MEBIBYTE * BYTES_PER_KIBIBYTE;
|
|
8
9
|
|
|
9
10
|
function assertFile(file: unknown): asserts file is File {
|
|
10
|
-
|
|
11
|
+
consola.debug("[ASSERT_FILE] Asserting file", { file });
|
|
11
12
|
if (!(file instanceof File)) {
|
|
12
13
|
throw new Error("file must be an instance of File");
|
|
13
14
|
}
|