@cloudnux/local-cloud-provider 0.11.0 → 0.14.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/dist/dev-console-plugin/index.d.ts +37 -2
- package/dist/dev-console-plugin/index.js +452 -249
- package/dist/dev-console-plugin/index.js.map +1 -1
- package/dist/index.js +191 -90
- package/dist/index.js.map +1 -1
- package/dist/queue-plugin/index.d.ts +2 -1
- package/dist/queue-plugin/index.js +187 -102
- package/dist/queue-plugin/index.js.map +1 -1
- package/dist/schedule-plugin/index.js +193 -118
- package/dist/schedule-plugin/index.js.map +1 -1
- package/dist/websocket-plugin/index.d.ts +10 -3
- package/dist/websocket-plugin/index.js +1063 -11
- package/dist/websocket-plugin/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,15 +1,6 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import fsPlugin3 from "fastify-plugin";
|
|
5
|
-
import { createRequire } from "module";
|
|
6
|
-
|
|
7
|
-
// src/queue-plugin/plugin.ts
|
|
8
|
-
import fsPlugin from "fastify-plugin";
|
|
9
|
-
|
|
10
|
-
// src/queue-plugin/core.ts
|
|
11
|
-
import chalk2 from "chalk";
|
|
12
|
-
import logSymbols from "log-symbols";
|
|
1
|
+
// src/logging/pretty-writer.ts
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { EOL as EOL2 } from "os";
|
|
13
4
|
|
|
14
5
|
// ../../../node_modules/lodash-es/_freeGlobal.js
|
|
15
6
|
var freeGlobal = typeof global == "object" && global && global.Object === Object && global;
|
|
@@ -457,8 +448,8 @@ ListCache.prototype.set = listCacheSet_default;
|
|
|
457
448
|
var ListCache_default = ListCache;
|
|
458
449
|
|
|
459
450
|
// ../../../node_modules/lodash-es/_Map.js
|
|
460
|
-
var
|
|
461
|
-
var Map_default =
|
|
451
|
+
var Map2 = getNative_default(root_default, "Map");
|
|
452
|
+
var Map_default = Map2;
|
|
462
453
|
|
|
463
454
|
// ../../../node_modules/lodash-es/_mapCacheClear.js
|
|
464
455
|
function mapCacheClear() {
|
|
@@ -833,20 +824,32 @@ var utils = {
|
|
|
833
824
|
};
|
|
834
825
|
var env = Object.assign(_env, utils);
|
|
835
826
|
|
|
836
|
-
// ../../utils/src/logging/index.ts
|
|
837
|
-
import chalk from "chalk";
|
|
838
|
-
import { EOL } from "os";
|
|
839
|
-
|
|
840
827
|
// ../../utils/src/logging/types.ts
|
|
841
828
|
var logLevels = {
|
|
842
829
|
fatal: -1,
|
|
843
830
|
error: 0,
|
|
844
831
|
warn: 1,
|
|
845
832
|
info: 2,
|
|
846
|
-
debug: 3
|
|
833
|
+
debug: 3,
|
|
834
|
+
trace: 4
|
|
847
835
|
};
|
|
848
836
|
|
|
849
837
|
// ../../utils/src/logging/error-to-string.ts
|
|
838
|
+
var safeJsonStringify = (value) => {
|
|
839
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
840
|
+
return JSON.stringify(value, (key, currentValue) => {
|
|
841
|
+
if (key === "constructor") return void 0;
|
|
842
|
+
if (typeof currentValue === "object" && currentValue !== null) {
|
|
843
|
+
if (seen.has(currentValue)) return "[Circular]";
|
|
844
|
+
seen.add(currentValue);
|
|
845
|
+
}
|
|
846
|
+
return currentValue;
|
|
847
|
+
});
|
|
848
|
+
};
|
|
849
|
+
var hasOwnConstructorProp = (value) => {
|
|
850
|
+
if (typeof value !== "object" || value === null) return false;
|
|
851
|
+
return Object.prototype.hasOwnProperty.call(value, "constructor");
|
|
852
|
+
};
|
|
850
853
|
var errorToString = (error) => {
|
|
851
854
|
if (error === null) return "Null error";
|
|
852
855
|
if (error === void 0) return "Undefined error";
|
|
@@ -856,13 +859,22 @@ var errorToString = (error) => {
|
|
|
856
859
|
`Message: ${error.message}`,
|
|
857
860
|
`Stack: ${error.stack || "No stack trace available"}`,
|
|
858
861
|
// Handle additional properties that might exist on custom errors
|
|
859
|
-
...Object.entries(error).filter(
|
|
862
|
+
...Object.entries(error).filter(
|
|
863
|
+
([key, value]) => !["name", "message", "stack"].includes(key) && !hasOwnConstructorProp(value)
|
|
864
|
+
).map(([key, value]) => `${key}: ${safeJsonStringify(value)}`)
|
|
860
865
|
].join("\n");
|
|
861
866
|
}
|
|
862
867
|
if (typeof error === "string") return error;
|
|
863
868
|
if (typeof error === "object") {
|
|
864
869
|
try {
|
|
865
|
-
return JSON.stringify(
|
|
870
|
+
return JSON.stringify(
|
|
871
|
+
error,
|
|
872
|
+
(key, value) => {
|
|
873
|
+
if (key === "constructor") return void 0;
|
|
874
|
+
return value;
|
|
875
|
+
},
|
|
876
|
+
2
|
|
877
|
+
);
|
|
866
878
|
} catch {
|
|
867
879
|
return `[Object that cannot be stringified: ${Object.prototype.toString.call(error)}]`;
|
|
868
880
|
}
|
|
@@ -870,62 +882,136 @@ var errorToString = (error) => {
|
|
|
870
882
|
return String(error);
|
|
871
883
|
};
|
|
872
884
|
|
|
873
|
-
// ../../utils/src/logging/
|
|
874
|
-
|
|
875
|
-
var
|
|
876
|
-
|
|
877
|
-
var logger = {
|
|
878
|
-
fatal: (message, meta) => {
|
|
879
|
-
if (currentLogLevel >= logLevels.fatal) {
|
|
880
|
-
console.error(
|
|
881
|
-
`[${(/* @__PURE__ */ new Date()).toTimeString()}]`,
|
|
882
|
-
`${chalk.bgRed.white(" fatal ")} - ${module || "unknown module"} - ${requestId || "no request ID"} - ${EOL}`,
|
|
883
|
-
errorToString(message),
|
|
884
|
-
meta ? `${EOL}${JSON.stringify(meta, null, 2)}` : ""
|
|
885
|
-
);
|
|
886
|
-
}
|
|
887
|
-
},
|
|
888
|
-
error: (message, meta) => {
|
|
889
|
-
if (currentLogLevel >= logLevels.error) {
|
|
890
|
-
console.error(
|
|
891
|
-
`[${(/* @__PURE__ */ new Date()).toTimeString()}]`,
|
|
892
|
-
`${chalk.bgRed.white(" error ")} - ${module || "unknown module"} - ${requestId || "no request ID"} - ${EOL}`,
|
|
893
|
-
errorToString(message),
|
|
894
|
-
meta ? `${EOL}${JSON.stringify(meta, null, 2)}` : ""
|
|
895
|
-
);
|
|
896
|
-
}
|
|
897
|
-
},
|
|
898
|
-
warn: (message, meta) => {
|
|
899
|
-
if (currentLogLevel >= logLevels.warn) {
|
|
900
|
-
console.warn(
|
|
901
|
-
`[${(/* @__PURE__ */ new Date()).toTimeString()}]`,
|
|
902
|
-
`${chalk.bgYellow.black(" warn ")} - ${module || "unknown module"} - ${requestId || "no request ID"} - ${EOL}`,
|
|
903
|
-
errorToString(message),
|
|
904
|
-
meta ? `${EOL}${JSON.stringify(meta, null, 2)}` : ""
|
|
905
|
-
);
|
|
906
|
-
}
|
|
907
|
-
},
|
|
908
|
-
info: (message, meta) => {
|
|
909
|
-
if (currentLogLevel >= logLevels.info) {
|
|
910
|
-
console.info(
|
|
911
|
-
`[${(/* @__PURE__ */ new Date()).toTimeString()}]`,
|
|
912
|
-
`${chalk.bgBlue.white(" info ")} - ${module || "unknown module"} - ${requestId || "no request ID"} - ${EOL}`,
|
|
913
|
-
message,
|
|
914
|
-
meta ? `${EOL}${JSON.stringify(meta, null, 2)}` : ""
|
|
915
|
-
);
|
|
916
|
-
}
|
|
917
|
-
},
|
|
918
|
-
debug: (message, meta) => {
|
|
919
|
-
if (currentLogLevel >= logLevels.debug) {
|
|
920
|
-
console.debug(
|
|
921
|
-
`[${(/* @__PURE__ */ new Date()).toTimeString()}]`,
|
|
922
|
-
`${chalk.bgWhite.black(" debug ")} - ${module || "unknown module"} - ${requestId || "no request ID"} - ${EOL}`,
|
|
923
|
-
message,
|
|
924
|
-
meta ? `${EOL}${JSON.stringify(meta, null, 2)}` : ""
|
|
925
|
-
);
|
|
926
|
-
}
|
|
927
|
-
}
|
|
885
|
+
// ../../utils/src/logging/writer.ts
|
|
886
|
+
import { EOL } from "os";
|
|
887
|
+
var jsonWriter = (entry) => {
|
|
888
|
+
process.stdout.write(JSON.stringify(entry) + EOL);
|
|
928
889
|
};
|
|
890
|
+
var _writer = jsonWriter;
|
|
891
|
+
function setWriter(writer) {
|
|
892
|
+
_writer = writer;
|
|
893
|
+
}
|
|
894
|
+
function getWriter() {
|
|
895
|
+
return _writer;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
// ../../utils/src/logging/index.ts
|
|
899
|
+
var levelValues = {
|
|
900
|
+
fatal: 70,
|
|
901
|
+
error: 60,
|
|
902
|
+
warn: 50,
|
|
903
|
+
info: 40,
|
|
904
|
+
debug: 30,
|
|
905
|
+
trace: 20
|
|
906
|
+
};
|
|
907
|
+
var currentLogLevel = 2;
|
|
908
|
+
var _module = "default";
|
|
909
|
+
var _requestId = "";
|
|
910
|
+
function writeLine(level, mergeObject, msg, bindings) {
|
|
911
|
+
getWriter()({
|
|
912
|
+
level: levelValues[level],
|
|
913
|
+
levelName: level,
|
|
914
|
+
time: Date.now(),
|
|
915
|
+
module: bindings.module || _module,
|
|
916
|
+
reqId: bindings.reqId || _requestId,
|
|
917
|
+
msg: level === "error" || level === "fatal" ? errorToString(msg) : msg,
|
|
918
|
+
...mergeObject ? { meta: mergeObject } : {}
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
function createLogger(bindings = {}) {
|
|
922
|
+
const currentLogLevelName = env("LOG_LEVEL")?.toLowerCase() ?? "info";
|
|
923
|
+
currentLogLevel = logLevels[currentLogLevelName] ?? logLevels.info;
|
|
924
|
+
return {
|
|
925
|
+
level: currentLogLevelName,
|
|
926
|
+
fatal: (mergeObject, msg) => {
|
|
927
|
+
if (currentLogLevel >= logLevels.fatal) {
|
|
928
|
+
typeof mergeObject === "string" || mergeObject instanceof Error ? writeLine("fatal", null, mergeObject, bindings) : writeLine("fatal", mergeObject, msg ?? "", bindings);
|
|
929
|
+
}
|
|
930
|
+
},
|
|
931
|
+
error: (mergeObject, msg) => {
|
|
932
|
+
if (currentLogLevel >= logLevels.error) {
|
|
933
|
+
typeof mergeObject === "string" || mergeObject instanceof Error ? writeLine("error", null, mergeObject, bindings) : writeLine("error", mergeObject, msg ?? "", bindings);
|
|
934
|
+
}
|
|
935
|
+
},
|
|
936
|
+
warn: (mergeObject, msg) => {
|
|
937
|
+
if (currentLogLevel >= logLevels.warn) {
|
|
938
|
+
typeof mergeObject === "string" ? writeLine("warn", null, mergeObject, bindings) : writeLine("warn", mergeObject, msg ?? "", bindings);
|
|
939
|
+
}
|
|
940
|
+
},
|
|
941
|
+
info: (mergeObject, msg) => {
|
|
942
|
+
if (currentLogLevel >= logLevels.info) {
|
|
943
|
+
typeof mergeObject === "string" ? writeLine("info", null, mergeObject, bindings) : writeLine("info", mergeObject, msg ?? "", bindings);
|
|
944
|
+
}
|
|
945
|
+
},
|
|
946
|
+
debug: (mergeObject, msg) => {
|
|
947
|
+
if (currentLogLevel >= logLevels.debug) {
|
|
948
|
+
typeof mergeObject === "string" ? writeLine("debug", null, mergeObject, bindings) : writeLine("debug", mergeObject, msg ?? "", bindings);
|
|
949
|
+
}
|
|
950
|
+
},
|
|
951
|
+
trace: (mergeObject, msg) => {
|
|
952
|
+
if (currentLogLevel >= logLevels.trace) {
|
|
953
|
+
typeof mergeObject === "string" ? writeLine("trace", null, mergeObject, bindings) : writeLine("trace", mergeObject, msg ?? "", bindings);
|
|
954
|
+
}
|
|
955
|
+
},
|
|
956
|
+
silent: () => {
|
|
957
|
+
},
|
|
958
|
+
child: (childBindings) => createLogger({ ...bindings, ...childBindings })
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
var logger = createLogger();
|
|
962
|
+
|
|
963
|
+
// src/logging/pretty-writer.ts
|
|
964
|
+
var levelColor = {
|
|
965
|
+
fatal: chalk.bgRed.white,
|
|
966
|
+
error: chalk.red,
|
|
967
|
+
warn: chalk.yellow,
|
|
968
|
+
info: chalk.cyan,
|
|
969
|
+
debug: chalk.gray,
|
|
970
|
+
trace: chalk.white
|
|
971
|
+
};
|
|
972
|
+
function formatTime(ms) {
|
|
973
|
+
return new Date(ms).toTimeString().slice(0, 8);
|
|
974
|
+
}
|
|
975
|
+
function formatMeta(meta) {
|
|
976
|
+
const { req, res, ...rest } = meta;
|
|
977
|
+
const lines = [];
|
|
978
|
+
if (req) {
|
|
979
|
+
const reqParts = [`${req.method} ${req.url}`];
|
|
980
|
+
if (req.remoteAddress) reqParts.push(`from ${req.remoteAddress}:${req.remotePort ?? ""}`);
|
|
981
|
+
if (req.headers) reqParts.push(`headers=${JSON.stringify(req.headers, null, 2)}`);
|
|
982
|
+
if (req.body !== void 0) reqParts.push(`body=${typeof req.body === "string" ? req.body : JSON.stringify(req.body, null, 2)}`);
|
|
983
|
+
lines.push(chalk.dim(" req: " + reqParts.join(" ")));
|
|
984
|
+
}
|
|
985
|
+
if (res) {
|
|
986
|
+
const resParts = [`${res.statusCode}`];
|
|
987
|
+
if (res.headers) resParts.push(`headers=${JSON.stringify(res.headers, null, 2)}`);
|
|
988
|
+
if (res.body !== void 0) resParts.push(`body=${typeof res.body === "string" ? res.body : JSON.stringify(res.body, null, 2)}`);
|
|
989
|
+
lines.push(chalk.dim(" res: " + resParts.join(" ")));
|
|
990
|
+
}
|
|
991
|
+
if (Object.keys(rest).length) {
|
|
992
|
+
lines.push(chalk.dim(" " + JSON.stringify(rest, null, 2)));
|
|
993
|
+
}
|
|
994
|
+
return lines.length ? EOL2 + lines.join(EOL2) : "";
|
|
995
|
+
}
|
|
996
|
+
var prettyWriter = (entry) => {
|
|
997
|
+
const color = levelColor[entry.levelName] ?? chalk.white;
|
|
998
|
+
const time = chalk.dim(formatTime(entry.time));
|
|
999
|
+
const level = color(entry.levelName.toUpperCase().padEnd(5));
|
|
1000
|
+
const module = chalk.magenta(entry.module);
|
|
1001
|
+
const reqId = entry.reqId ? chalk.dim(`[${entry.reqId}]`) + " " : "";
|
|
1002
|
+
const meta = entry.meta ? formatMeta(entry.meta) : "";
|
|
1003
|
+
process.stdout.write(`${time} ${level} ${module} ${reqId}- ${entry.msg}${meta}${EOL2}`);
|
|
1004
|
+
};
|
|
1005
|
+
setWriter(prettyWriter);
|
|
1006
|
+
|
|
1007
|
+
// src/dev-console-plugin/plugin.ts
|
|
1008
|
+
import path3 from "path";
|
|
1009
|
+
import fastifyStatic from "@fastify/static";
|
|
1010
|
+
import fsPlugin4 from "fastify-plugin";
|
|
1011
|
+
import { createRequire } from "module";
|
|
1012
|
+
|
|
1013
|
+
// src/queue-plugin/plugin.ts
|
|
1014
|
+
import fsPlugin from "fastify-plugin";
|
|
929
1015
|
|
|
930
1016
|
// src/queue-plugin/core.ts
|
|
931
1017
|
var DEFAULT_CONFIG = {
|
|
@@ -951,14 +1037,14 @@ var mergeConfig = (defaultConfig, userConfig) => ({
|
|
|
951
1037
|
...userConfig?.persistence || {}
|
|
952
1038
|
}
|
|
953
1039
|
});
|
|
954
|
-
var createQueueService = (handler,
|
|
1040
|
+
var createQueueService = (handler, module) => ({
|
|
955
1041
|
handler,
|
|
956
1042
|
incoming: [],
|
|
957
1043
|
processing: [],
|
|
958
1044
|
dlq: [],
|
|
959
1045
|
timeoutId: null,
|
|
960
1046
|
processingBatch: false,
|
|
961
|
-
module
|
|
1047
|
+
module
|
|
962
1048
|
});
|
|
963
1049
|
var createQueueMessage = (body, headers) => {
|
|
964
1050
|
const id = Date.now().toString() + Math.random().toString(36).substring(2, 7);
|
|
@@ -1039,32 +1125,36 @@ var purgeDLQ = (queueService) => {
|
|
|
1039
1125
|
return dlqCount;
|
|
1040
1126
|
};
|
|
1041
1127
|
var logSuccess = (message, messageId, queueName) => {
|
|
1042
|
-
logger.debug(
|
|
1128
|
+
logger.debug(`Success: ${message} ${messageId} in queue ${queueName}`);
|
|
1043
1129
|
};
|
|
1044
1130
|
var logError = (message, messageId, queueName, error) => {
|
|
1045
|
-
logger.error(
|
|
1131
|
+
logger.error(`Error: ${message} ${messageId} in queue ${queueName}: ${error}`);
|
|
1046
1132
|
};
|
|
1047
1133
|
var logRetryScheduled = (messageId, delayMs) => {
|
|
1048
|
-
logger.debug(
|
|
1134
|
+
logger.debug(`Scheduling retry for message ${messageId} in ${delayMs}ms`);
|
|
1049
1135
|
};
|
|
1050
1136
|
var logDLQOperation = (operation, count, queueName) => {
|
|
1051
|
-
logger.warn(`${
|
|
1137
|
+
logger.warn(`${operation} ${count} messages from DLQ for ${queueName}`);
|
|
1052
1138
|
};
|
|
1053
1139
|
|
|
1054
1140
|
// src/queue-plugin/processing.ts
|
|
1055
1141
|
var createProcessMessageHandler = (config) => async (queueName, message, queueService) => {
|
|
1056
1142
|
try {
|
|
1057
|
-
await queueService.handler(message);
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1143
|
+
const result = await queueService.handler(message);
|
|
1144
|
+
if (result?.failureId) {
|
|
1145
|
+
await handleProcessingError(queueName, message, queueService, config);
|
|
1146
|
+
} else {
|
|
1147
|
+
removeFromProcessing(queueService, message.id);
|
|
1148
|
+
logSuccess("Successfully processed message", message.id, queueName);
|
|
1149
|
+
}
|
|
1150
|
+
} catch {
|
|
1151
|
+
await handleProcessingError(queueName, message, queueService, config);
|
|
1062
1152
|
}
|
|
1063
1153
|
};
|
|
1064
|
-
var handleProcessingError = async (queueName, message, queueService,
|
|
1065
|
-
logError("Error processing message", message.id, queueName,
|
|
1154
|
+
var handleProcessingError = async (queueName, message, queueService, config) => {
|
|
1155
|
+
logError("Error processing message", message.id, queueName, "handler returned failure");
|
|
1066
1156
|
if (message.attempts >= config.maxRetries) {
|
|
1067
|
-
moveToDLQ(queueService, message,
|
|
1157
|
+
moveToDLQ(queueService, message, "max retries exceeded");
|
|
1068
1158
|
return;
|
|
1069
1159
|
}
|
|
1070
1160
|
const updatedMessage = incrementAttempts(queueService, message.id);
|
|
@@ -1124,8 +1214,6 @@ var handleImmediateProcessing = (queueService, config, processBatch, queueName)
|
|
|
1124
1214
|
// src/queue-plugin/persistence.ts
|
|
1125
1215
|
import * as fs from "fs/promises";
|
|
1126
1216
|
import * as path from "path";
|
|
1127
|
-
import chalk3 from "chalk";
|
|
1128
|
-
import logSymbols2 from "log-symbols";
|
|
1129
1217
|
var createQueueData = (queueService) => ({
|
|
1130
1218
|
incoming: queueService.incoming,
|
|
1131
1219
|
processing: queueService.processing,
|
|
@@ -1160,10 +1248,9 @@ var createPersistenceInitializer = (config, loadAllQueueStates, saveDirtyQueueSt
|
|
|
1160
1248
|
process.on("SIGINT", shutdownHandler);
|
|
1161
1249
|
process.on("SIGTERM", shutdownHandler);
|
|
1162
1250
|
}
|
|
1163
|
-
logger.debug(
|
|
1251
|
+
logger.debug(`Queue persistence initialized: ${config.persistence.directory}`);
|
|
1164
1252
|
} catch (error) {
|
|
1165
|
-
|
|
1166
|
-
logger.error(`${logSymbols2.error} ${chalk3.red("Failed to initialize queue persistence:")} ${chalk3.yellow(error?.message)}`);
|
|
1253
|
+
logger.error(`Failed to initialize queue persistence: ${error?.message}`);
|
|
1167
1254
|
}
|
|
1168
1255
|
};
|
|
1169
1256
|
var createQueueStateSaver = (config) => async (queueName, queueService) => {
|
|
@@ -1175,7 +1262,7 @@ var createQueueStateSaver = (config) => async (queueName, queueService) => {
|
|
|
1175
1262
|
const tempFilePath = path.join(config.persistence.directory, `${queueName}.${now}temp.json`);
|
|
1176
1263
|
await fs.writeFile(tempFilePath, JSON.stringify(queueData, null, 2), "utf8");
|
|
1177
1264
|
await fs.rename(tempFilePath, queueFilePath);
|
|
1178
|
-
logger.debug(
|
|
1265
|
+
logger.debug(`Queue state saved: ${queueName}`);
|
|
1179
1266
|
} catch (error) {
|
|
1180
1267
|
logger.error(`Failed to save queue state for ${queueName}:`, error?.message);
|
|
1181
1268
|
}
|
|
@@ -1185,9 +1272,9 @@ var createAllQueuesStateSaver = (config, saveQueueState) => (queues) => async ()
|
|
|
1185
1272
|
for (const [queueName, queueService] of Object.entries(queues)) {
|
|
1186
1273
|
await saveQueueState(queueName, queueService);
|
|
1187
1274
|
}
|
|
1188
|
-
logger.debug(
|
|
1275
|
+
logger.debug(`All queue states saved to ${config.persistence.directory}`);
|
|
1189
1276
|
} catch (error) {
|
|
1190
|
-
logger.error(
|
|
1277
|
+
logger.error(`Failed to save all queue states: ${error?.message}`);
|
|
1191
1278
|
}
|
|
1192
1279
|
};
|
|
1193
1280
|
var createDirtyQueuesStateSaver = (saveQueueState, dirtyQueues) => (queues) => async () => {
|
|
@@ -1201,7 +1288,7 @@ var createDirtyQueuesStateSaver = (saveQueueState, dirtyQueues) => (queues) => a
|
|
|
1201
1288
|
}
|
|
1202
1289
|
}
|
|
1203
1290
|
} catch (error) {
|
|
1204
|
-
logger.error(
|
|
1291
|
+
logger.error(`Failed to save dirty queue states: ${error?.message}`);
|
|
1205
1292
|
}
|
|
1206
1293
|
};
|
|
1207
1294
|
var createQueueStateLoader = (config, scheduleProcessing, processMessage) => (queues) => async (queueName) => {
|
|
@@ -1313,8 +1400,6 @@ var registerQueueRoutes = (app, prefix = "") => {
|
|
|
1313
1400
|
};
|
|
1314
1401
|
|
|
1315
1402
|
// src/queue-plugin/decorator.ts
|
|
1316
|
-
import chalk4 from "chalk";
|
|
1317
|
-
import logSymbols3 from "log-symbols";
|
|
1318
1403
|
var isValidQueueName = (queueName) => {
|
|
1319
1404
|
return typeof queueName === "string" && queueName.length > 0 && /^[a-zA-Z0-9_-]+$/.test(queueName);
|
|
1320
1405
|
};
|
|
@@ -1340,21 +1425,21 @@ var createQueueManager = ({
|
|
|
1340
1425
|
throw new Error("Handler must be a function");
|
|
1341
1426
|
}
|
|
1342
1427
|
};
|
|
1343
|
-
const addQueue = async (queueName, handler,
|
|
1428
|
+
const addQueue = async (queueName, handler, module) => {
|
|
1344
1429
|
try {
|
|
1345
1430
|
validateQueueName(queueName);
|
|
1346
1431
|
validateHandler(handler);
|
|
1347
1432
|
if (queues[queueName]) {
|
|
1348
|
-
logger.warn(
|
|
1433
|
+
logger.warn(`Queue already exists: ${queueName}.`);
|
|
1349
1434
|
return;
|
|
1350
1435
|
}
|
|
1351
|
-
queues[queueName] = createQueueService(handler,
|
|
1436
|
+
queues[queueName] = createQueueService(handler, module);
|
|
1352
1437
|
if (config.persistence.enabled && loadQueueState) {
|
|
1353
1438
|
await loadQueueState(queueName);
|
|
1354
1439
|
}
|
|
1355
|
-
logger.info(
|
|
1440
|
+
logger.info(`Queue added: ${queueName}`);
|
|
1356
1441
|
} catch (error) {
|
|
1357
|
-
logger.error(
|
|
1442
|
+
logger.error(`Failed to add queue ${queueName}: ${error.message}`);
|
|
1358
1443
|
throw error;
|
|
1359
1444
|
}
|
|
1360
1445
|
};
|
|
@@ -1367,7 +1452,7 @@ var createQueueManager = ({
|
|
|
1367
1452
|
const queueService = queues[queueName];
|
|
1368
1453
|
const totalMessages = queueService.incoming.length + queueService.processing.length;
|
|
1369
1454
|
if (totalMessages > 0) {
|
|
1370
|
-
logger.warn(
|
|
1455
|
+
logger.warn(`Removing queue with ${totalMessages} pending messages: ${queueName}`);
|
|
1371
1456
|
}
|
|
1372
1457
|
if (queueService.timeoutId) {
|
|
1373
1458
|
clearTimeout(queueService.timeoutId);
|
|
@@ -1376,9 +1461,9 @@ var createQueueManager = ({
|
|
|
1376
1461
|
await saveQueueState(queueName, queueService);
|
|
1377
1462
|
}
|
|
1378
1463
|
delete queues[queueName];
|
|
1379
|
-
logger.info(
|
|
1464
|
+
logger.info(`Queue removed: ${queueName}`);
|
|
1380
1465
|
} catch (error) {
|
|
1381
|
-
logger.error(
|
|
1466
|
+
logger.error(`Failed to remove queue ${queueName}: ${error.message}`);
|
|
1382
1467
|
throw error;
|
|
1383
1468
|
}
|
|
1384
1469
|
};
|
|
@@ -1390,10 +1475,10 @@ var createQueueManager = ({
|
|
|
1390
1475
|
return false;
|
|
1391
1476
|
}
|
|
1392
1477
|
};
|
|
1393
|
-
const listQueues = (
|
|
1478
|
+
const listQueues = (module) => {
|
|
1394
1479
|
return Object.keys(queues).filter((queueName) => {
|
|
1395
1480
|
const queueService = queues[queueName];
|
|
1396
|
-
return !
|
|
1481
|
+
return !module || queueService.module === module;
|
|
1397
1482
|
}).sort();
|
|
1398
1483
|
};
|
|
1399
1484
|
const getQueueStats = (queueName) => {
|
|
@@ -1555,15 +1640,8 @@ import fsPlugin2 from "fastify-plugin";
|
|
|
1555
1640
|
|
|
1556
1641
|
// src/schedule-plugin/core.ts
|
|
1557
1642
|
import * as fs3 from "fs/promises";
|
|
1558
|
-
import chalk9 from "chalk";
|
|
1559
|
-
import logSymbols7 from "log-symbols";
|
|
1560
|
-
|
|
1561
|
-
// src/schedule-plugin/execution.ts
|
|
1562
|
-
import chalk6 from "chalk";
|
|
1563
|
-
import logSymbols4 from "log-symbols";
|
|
1564
1643
|
|
|
1565
1644
|
// src/schedule-plugin/cron-utils.ts
|
|
1566
|
-
import chalk5 from "chalk";
|
|
1567
1645
|
import { parseExpression } from "cron-parser";
|
|
1568
1646
|
function parseCronExpression(cronExpression, lastRun, options = {}) {
|
|
1569
1647
|
const {
|
|
@@ -1595,7 +1673,7 @@ function parseCronExpression(cronExpression, lastRun, options = {}) {
|
|
|
1595
1673
|
description: describeCronExpression(normalizedCron)
|
|
1596
1674
|
};
|
|
1597
1675
|
} catch (error) {
|
|
1598
|
-
logger.error(
|
|
1676
|
+
logger.error(`Invalid cron expression: ${cronExpression} - ${error.message}`);
|
|
1599
1677
|
const fallbackTime = /* @__PURE__ */ new Date();
|
|
1600
1678
|
fallbackTime.setHours(fallbackTime.getHours() + 1);
|
|
1601
1679
|
fallbackTime.setMinutes(0);
|
|
@@ -1624,7 +1702,7 @@ function getNextExecutions(cronExpression, count = 5, options = {}) {
|
|
|
1624
1702
|
}
|
|
1625
1703
|
return executions;
|
|
1626
1704
|
} catch (error) {
|
|
1627
|
-
logger.error(
|
|
1705
|
+
logger.error(`Error getting next executions: ${error.message}`);
|
|
1628
1706
|
return [];
|
|
1629
1707
|
}
|
|
1630
1708
|
}
|
|
@@ -1939,7 +2017,7 @@ var scheduleJob = (scheduler, state, executeJobFn) => {
|
|
|
1939
2017
|
updatedScheduler.timerId = setTimeout(() => {
|
|
1940
2018
|
executeJobFn(updatedScheduler);
|
|
1941
2019
|
}, timeUntilNextRun);
|
|
1942
|
-
logger.debug(
|
|
2020
|
+
logger.debug(`Scheduled job ${scheduler.job.name} to run in ${Math.round(timeUntilNextRun / 1e3)}s`);
|
|
1943
2021
|
}
|
|
1944
2022
|
return updatedScheduler;
|
|
1945
2023
|
};
|
|
@@ -1968,20 +2046,18 @@ var updateJobAfterExecution = (job, execution, config) => {
|
|
|
1968
2046
|
return updatedJob;
|
|
1969
2047
|
};
|
|
1970
2048
|
var handleExecutionError = (execution, error) => {
|
|
1971
|
-
logger.error(
|
|
2049
|
+
logger.error(`Job failed ${execution.jobId}: ${error.message}`);
|
|
1972
2050
|
return completeExecution(execution, void 0, error.message);
|
|
1973
2051
|
};
|
|
1974
2052
|
var handleExecutionSuccess = (execution, result) => {
|
|
1975
2053
|
const duration = execution.endTime ? execution.endTime.getTime() - execution.startTime.getTime() : 0;
|
|
1976
|
-
logger.debug(
|
|
2054
|
+
logger.debug(`Job completed in ${duration}ms`);
|
|
1977
2055
|
return completeExecution(execution, result);
|
|
1978
2056
|
};
|
|
1979
2057
|
|
|
1980
2058
|
// src/schedule-plugin/persistence.ts
|
|
1981
2059
|
import * as fs2 from "fs/promises";
|
|
1982
2060
|
import * as path2 from "path";
|
|
1983
|
-
import chalk7 from "chalk";
|
|
1984
|
-
import logSymbols5 from "log-symbols";
|
|
1985
2061
|
var createStateFilePath = (directory) => path2.join(directory, "scheduler-state.json");
|
|
1986
2062
|
var createTempFilePath = (directory) => path2.join(directory, `scheduler-state.${Date.now()}.temp.json`);
|
|
1987
2063
|
var serializeSchedulerState = (schedulers, executionHistory) => ({
|
|
@@ -1997,7 +2073,7 @@ var saveSchedulerState = async (state) => {
|
|
|
1997
2073
|
const tempFile = createTempFilePath(state.config.persistence.directory);
|
|
1998
2074
|
await fs2.writeFile(tempFile, JSON.stringify(serializedState, null, 2), "utf8");
|
|
1999
2075
|
await fs2.rename(tempFile, stateFile);
|
|
2000
|
-
logger.debug(
|
|
2076
|
+
logger.debug("Enhanced scheduler state saved");
|
|
2001
2077
|
} catch (error) {
|
|
2002
2078
|
logger.error("Failed to save scheduler state:", error);
|
|
2003
2079
|
}
|
|
@@ -2009,7 +2085,7 @@ var loadSchedulerStateData = async (directory) => {
|
|
|
2009
2085
|
return JSON.parse(data);
|
|
2010
2086
|
} catch (error) {
|
|
2011
2087
|
if (error.code === "ENOENT") {
|
|
2012
|
-
logger.debug(
|
|
2088
|
+
logger.debug("No previous scheduler state found - starting fresh");
|
|
2013
2089
|
} else {
|
|
2014
2090
|
logger.error("Failed to load scheduler state:", error);
|
|
2015
2091
|
}
|
|
@@ -2022,20 +2098,20 @@ var validateAndAdjustNextRun = (job, savedNextRun, lastRestartTime, config) => {
|
|
|
2022
2098
|
return calculateNextRunFromLastRun(job, job.lastRun, config);
|
|
2023
2099
|
}
|
|
2024
2100
|
if (savedNextRun <= now) {
|
|
2025
|
-
logger.debug(
|
|
2101
|
+
logger.debug(`Saved next run is in the past for ${job.name} - recalculating`);
|
|
2026
2102
|
return calculateNextRunFromLastRun(job, job.lastRun, config);
|
|
2027
2103
|
}
|
|
2028
2104
|
const timeSinceRestart = now.getTime() - lastRestartTime.getTime();
|
|
2029
2105
|
const isRapidRestart = timeSinceRestart < config.restartBehavior.rapidRestartThreshold;
|
|
2030
2106
|
if (isRapidRestart) {
|
|
2031
|
-
logger.debug(
|
|
2107
|
+
logger.debug(`Rapid restart detected for ${job.name} - preserving saved timing`);
|
|
2032
2108
|
return savedNextRun;
|
|
2033
2109
|
}
|
|
2034
2110
|
if (job.cronExpression || job.intervalMs) {
|
|
2035
2111
|
const expectedNextRun = calculateNextRunFromLastRun(job, job.lastRun, config);
|
|
2036
2112
|
const timeDiff = Math.abs(savedNextRun.getTime() - expectedNextRun.getTime());
|
|
2037
2113
|
if (timeDiff > config.restartBehavior.maxTimingDrift) {
|
|
2038
|
-
logger.debug(
|
|
2114
|
+
logger.debug(`Adjusting timing for ${job.name} - drift of ${Math.round(timeDiff / 1e3)}s detected`);
|
|
2039
2115
|
return expectedNextRun;
|
|
2040
2116
|
}
|
|
2041
2117
|
}
|
|
@@ -2049,7 +2125,7 @@ var restoreJobFromSavedData = (scheduler, savedJob, config, lastRestartTime) =>
|
|
|
2049
2125
|
lastRun: savedJob.lastRun ? new Date(savedJob.lastRun) : void 0
|
|
2050
2126
|
};
|
|
2051
2127
|
if (definitionChanged) {
|
|
2052
|
-
logger.debug(
|
|
2128
|
+
logger.debug(`Job definition changed: ${savedJob.name} - recalculating schedule`);
|
|
2053
2129
|
updatedJob.nextRun = calculateNextRunFromLastRun(updatedJob, updatedJob.lastRun, config);
|
|
2054
2130
|
} else {
|
|
2055
2131
|
const savedNextRun = savedJob.nextRun ? new Date(savedJob.nextRun) : void 0;
|
|
@@ -2059,7 +2135,7 @@ var restoreJobFromSavedData = (scheduler, savedJob, config, lastRestartTime) =>
|
|
|
2059
2135
|
const result = parseCronExpression(updatedJob.cronExpression, updatedJob.lastRun, {
|
|
2060
2136
|
timezone: updatedJob.timezone
|
|
2061
2137
|
});
|
|
2062
|
-
logger.debug(
|
|
2138
|
+
logger.debug(`Job restored: ${savedJob.name} - ${result.description} - next: ${updatedJob.nextRun.toLocaleString()}`);
|
|
2063
2139
|
}
|
|
2064
2140
|
return { ...scheduler, job: updatedJob };
|
|
2065
2141
|
};
|
|
@@ -2089,20 +2165,18 @@ var loadSchedulerState = async (schedulers, config, lastRestartTime) => {
|
|
|
2089
2165
|
}
|
|
2090
2166
|
}
|
|
2091
2167
|
const executionHistory = stateData.executions ? restoreExecutionHistory(stateData.executions) : [];
|
|
2092
|
-
logger.debug(
|
|
2168
|
+
logger.debug(`Enhanced scheduler state loaded (saved at ${stateData.savedAt})`);
|
|
2093
2169
|
return { schedulers: restoredSchedulers, executionHistory };
|
|
2094
2170
|
};
|
|
2095
2171
|
|
|
2096
2172
|
// src/schedule-plugin/cleanup.ts
|
|
2097
|
-
import chalk8 from "chalk";
|
|
2098
|
-
import logSymbols6 from "log-symbols";
|
|
2099
2173
|
var cleanupExecutionHistory = (state) => {
|
|
2100
2174
|
if (state.executionHistory.length > state.config.cleanup.maxExecutionHistory) {
|
|
2101
2175
|
const removed = state.executionHistory.splice(
|
|
2102
2176
|
0,
|
|
2103
2177
|
state.executionHistory.length - state.config.cleanup.maxExecutionHistory
|
|
2104
2178
|
);
|
|
2105
|
-
logger.debug(
|
|
2179
|
+
logger.debug(`Cleaned up ${removed.length} old execution records`);
|
|
2106
2180
|
return removed;
|
|
2107
2181
|
}
|
|
2108
2182
|
return [];
|
|
@@ -2169,11 +2243,11 @@ var createSchedulerFunctions = (state) => {
|
|
|
2169
2243
|
const { canExecute, reason } = canExecuteJob(scheduler, state);
|
|
2170
2244
|
if (!canExecute) {
|
|
2171
2245
|
if (reason === "Maximum concurrent executions reached") {
|
|
2172
|
-
logger.warn(
|
|
2246
|
+
logger.warn(`Delaying job ${scheduler.job.name} - ${reason}`);
|
|
2173
2247
|
scheduler.job.nextRun = new Date(Date.now() + 3e4);
|
|
2174
2248
|
scheduleJobFn(scheduler);
|
|
2175
2249
|
} else if (reason === "Job reached maximum runs") {
|
|
2176
|
-
logger.info(
|
|
2250
|
+
logger.info(`Job ${scheduler.job.name} reached max runs (${scheduler.job.maxRuns})`);
|
|
2177
2251
|
}
|
|
2178
2252
|
return;
|
|
2179
2253
|
}
|
|
@@ -2182,7 +2256,7 @@ var createSchedulerFunctions = (state) => {
|
|
|
2182
2256
|
state.executionHistory.push(execution);
|
|
2183
2257
|
scheduler.isRunning = true;
|
|
2184
2258
|
state.runningExecutions++;
|
|
2185
|
-
logger.info(
|
|
2259
|
+
logger.info(`Executing job ${scheduler.job.name} (${execution.id})`);
|
|
2186
2260
|
try {
|
|
2187
2261
|
const result = await executeJobWithTimeout(
|
|
2188
2262
|
scheduler.handler,
|
|
@@ -2242,20 +2316,18 @@ var initializeScheduler = async (state, scheduleJobFn) => {
|
|
|
2242
2316
|
scheduleJobFn(scheduler);
|
|
2243
2317
|
}
|
|
2244
2318
|
}
|
|
2245
|
-
logger.debug(
|
|
2319
|
+
logger.debug(`Scheduler initialized: ${Object.keys(state.schedulers).length} jobs loaded`);
|
|
2246
2320
|
} catch (error) {
|
|
2247
|
-
logger.error(
|
|
2321
|
+
logger.error(`Failed to initialize scheduler: ${error.message}`);
|
|
2248
2322
|
throw error;
|
|
2249
2323
|
}
|
|
2250
2324
|
};
|
|
2251
2325
|
|
|
2252
2326
|
// src/schedule-plugin/jobs.ts
|
|
2253
|
-
import chalk10 from "chalk";
|
|
2254
|
-
import logSymbols8 from "log-symbols";
|
|
2255
2327
|
var validateJobDefinition = (jobDef) => {
|
|
2256
2328
|
const expressionType = detectExpressionType(jobDef.cronExpression);
|
|
2257
2329
|
if (expressionType === "unknown") {
|
|
2258
|
-
logger.error(
|
|
2330
|
+
logger.error(`Invalid cron expression for job: ${jobDef.name}`);
|
|
2259
2331
|
throw new Error(`Invalid cron expression for job: ${jobDef.name}`);
|
|
2260
2332
|
}
|
|
2261
2333
|
};
|
|
@@ -2267,11 +2339,11 @@ var createJobFromDefinition = (jobDef, config) => {
|
|
|
2267
2339
|
const result = parseCronExpression(cronExpression, void 0, {
|
|
2268
2340
|
timezone: jobDef.timezone ?? config.cron.defaultTimezone
|
|
2269
2341
|
});
|
|
2270
|
-
logger.debug(
|
|
2342
|
+
logger.debug(`Job ${jobDef.name}: ${result.description} - Next: ${result.nextRun.toLocaleString()}`);
|
|
2271
2343
|
const upcoming = getNextExecutions(cronExpression, 3, {
|
|
2272
2344
|
timezone: jobDef.timezone ?? config.cron.defaultTimezone
|
|
2273
2345
|
});
|
|
2274
|
-
logger.debug(
|
|
2346
|
+
logger.debug(`Upcoming: ${upcoming.map((d) => d.toLocaleTimeString()).join(", ")}`);
|
|
2275
2347
|
}
|
|
2276
2348
|
const job = {
|
|
2277
2349
|
id: generateJobId(),
|
|
@@ -2391,8 +2463,6 @@ var registerAllRoutes = (app, state, executeJobFn, scheduleJobFn) => {
|
|
|
2391
2463
|
};
|
|
2392
2464
|
|
|
2393
2465
|
// src/schedule-plugin/decorator.ts
|
|
2394
|
-
import chalk11 from "chalk";
|
|
2395
|
-
import logSymbols9 from "log-symbols";
|
|
2396
2466
|
var isValidJobName = (jobName) => {
|
|
2397
2467
|
return typeof jobName === "string" && jobName.length > 0 && /^[a-zA-Z0-9_-]+$/.test(jobName);
|
|
2398
2468
|
};
|
|
@@ -2422,7 +2492,7 @@ var createSchedulerManager = ({
|
|
|
2422
2492
|
validateJobDefinition(jobDefinition);
|
|
2423
2493
|
const existingJob = Object.values(state.schedulers).find((s) => s.job.name === jobDefinition.name);
|
|
2424
2494
|
if (existingJob) {
|
|
2425
|
-
logger.warn(
|
|
2495
|
+
logger.warn(`Job already exists: ${jobDefinition.name}.`);
|
|
2426
2496
|
return existingJob.job.id;
|
|
2427
2497
|
}
|
|
2428
2498
|
const job = createJobFromDefinition(jobDefinition, config);
|
|
@@ -2431,10 +2501,10 @@ var createSchedulerManager = ({
|
|
|
2431
2501
|
if (job.enabled) {
|
|
2432
2502
|
scheduleJobFn(scheduler);
|
|
2433
2503
|
}
|
|
2434
|
-
logger.info(
|
|
2504
|
+
logger.info(`Job added: ${jobDefinition.name} (${job.id})`);
|
|
2435
2505
|
return job.id;
|
|
2436
2506
|
} catch (error) {
|
|
2437
|
-
logger.error(
|
|
2507
|
+
logger.error(`Failed to add job ${jobDefinition.name}: ${error.message}`);
|
|
2438
2508
|
throw error;
|
|
2439
2509
|
}
|
|
2440
2510
|
};
|
|
@@ -2446,15 +2516,15 @@ var createSchedulerManager = ({
|
|
|
2446
2516
|
throw new Error(`Job '${jobName}' does not exist`);
|
|
2447
2517
|
}
|
|
2448
2518
|
if (scheduler.isRunning) {
|
|
2449
|
-
logger.warn(
|
|
2519
|
+
logger.warn(`Removing job that is currently running: ${jobName}`);
|
|
2450
2520
|
}
|
|
2451
2521
|
if (scheduler.timerId) {
|
|
2452
2522
|
clearTimeout(scheduler.timerId);
|
|
2453
2523
|
}
|
|
2454
2524
|
delete state.schedulers[scheduler.job.id];
|
|
2455
|
-
logger.info(
|
|
2525
|
+
logger.info(`Job removed: ${jobName}`);
|
|
2456
2526
|
} catch (error) {
|
|
2457
|
-
logger.error(
|
|
2527
|
+
logger.error(`Failed to remove job ${jobName}: ${error.message}`);
|
|
2458
2528
|
throw error;
|
|
2459
2529
|
}
|
|
2460
2530
|
};
|
|
@@ -2466,8 +2536,8 @@ var createSchedulerManager = ({
|
|
|
2466
2536
|
return false;
|
|
2467
2537
|
}
|
|
2468
2538
|
};
|
|
2469
|
-
const listJobs = (
|
|
2470
|
-
return Object.values(state.schedulers).filter((s) => !
|
|
2539
|
+
const listJobs = (module) => {
|
|
2540
|
+
return Object.values(state.schedulers).filter((s) => !module || s.job.module === module).map((s) => s.job.name).sort();
|
|
2471
2541
|
};
|
|
2472
2542
|
const getJobStats = (jobName) => {
|
|
2473
2543
|
try {
|
|
@@ -2486,14 +2556,14 @@ var createSchedulerManager = ({
|
|
|
2486
2556
|
throw new Error(`Job '${jobName}' does not exist`);
|
|
2487
2557
|
}
|
|
2488
2558
|
if (scheduler.job.enabled) {
|
|
2489
|
-
logger.debug(
|
|
2559
|
+
logger.debug(`Job is already enabled: ${jobName}`);
|
|
2490
2560
|
return;
|
|
2491
2561
|
}
|
|
2492
2562
|
scheduler.job.enabled = true;
|
|
2493
2563
|
scheduleJobFn(scheduler);
|
|
2494
|
-
logger.info(
|
|
2564
|
+
logger.info(`Job enabled: ${jobName}`);
|
|
2495
2565
|
} catch (error) {
|
|
2496
|
-
logger.error(
|
|
2566
|
+
logger.error(`Failed to enable job ${jobName}: ${error.message}`);
|
|
2497
2567
|
throw error;
|
|
2498
2568
|
}
|
|
2499
2569
|
};
|
|
@@ -2505,7 +2575,7 @@ var createSchedulerManager = ({
|
|
|
2505
2575
|
throw new Error(`Job '${jobName}' does not exist`);
|
|
2506
2576
|
}
|
|
2507
2577
|
if (!scheduler.job.enabled) {
|
|
2508
|
-
logger.debug(
|
|
2578
|
+
logger.debug(`Job is already disabled: ${jobName}`);
|
|
2509
2579
|
return;
|
|
2510
2580
|
}
|
|
2511
2581
|
scheduler.job.enabled = false;
|
|
@@ -2513,9 +2583,9 @@ var createSchedulerManager = ({
|
|
|
2513
2583
|
clearTimeout(scheduler.timerId);
|
|
2514
2584
|
scheduler.timerId = void 0;
|
|
2515
2585
|
}
|
|
2516
|
-
logger.info(
|
|
2586
|
+
logger.info(`Job disabled: ${jobName}`);
|
|
2517
2587
|
} catch (error) {
|
|
2518
|
-
logger.error(
|
|
2588
|
+
logger.error(`Failed to disable job ${jobName}: ${error.message}`);
|
|
2519
2589
|
throw error;
|
|
2520
2590
|
}
|
|
2521
2591
|
};
|
|
@@ -2530,9 +2600,9 @@ var createSchedulerManager = ({
|
|
|
2530
2600
|
throw new Error(`Job '${jobName}' is already running`);
|
|
2531
2601
|
}
|
|
2532
2602
|
setImmediate(() => executeJob(scheduler));
|
|
2533
|
-
logger.info(
|
|
2603
|
+
logger.info(`Job triggered: ${jobName}`);
|
|
2534
2604
|
} catch (error) {
|
|
2535
|
-
logger.error(
|
|
2605
|
+
logger.error(`Failed to trigger job ${jobName}: ${error.message}`);
|
|
2536
2606
|
throw error;
|
|
2537
2607
|
}
|
|
2538
2608
|
};
|
|
@@ -2572,10 +2642,141 @@ var schedulerPlugin = fsPlugin2(async (app, options) => {
|
|
|
2572
2642
|
registerAllRoutes(app, state, executeJob, scheduleJobFn);
|
|
2573
2643
|
});
|
|
2574
2644
|
|
|
2645
|
+
// src/websocket-plugin/plugin.ts
|
|
2646
|
+
import crypto from "crypto";
|
|
2647
|
+
import fsPlugin3 from "fastify-plugin";
|
|
2648
|
+
import websocketPlugin from "@fastify/websocket";
|
|
2649
|
+
var DEFAULT_CONFIG3 = {
|
|
2650
|
+
routeKeyField: "action"
|
|
2651
|
+
};
|
|
2652
|
+
function mergeConfig3(defaults, overrides) {
|
|
2653
|
+
return { ...defaults, ...overrides };
|
|
2654
|
+
}
|
|
2655
|
+
var websocketsPlugin = fsPlugin3(async (app, options) => {
|
|
2656
|
+
const config = mergeConfig3(DEFAULT_CONFIG3, options.config);
|
|
2657
|
+
const connections = /* @__PURE__ */ new Map();
|
|
2658
|
+
const handlers = [];
|
|
2659
|
+
const registeredPaths = /* @__PURE__ */ new Set();
|
|
2660
|
+
const pathModuleMap = /* @__PURE__ */ new Map();
|
|
2661
|
+
await app.register(websocketPlugin);
|
|
2662
|
+
function ensureRouteForPath(path4) {
|
|
2663
|
+
if (registeredPaths.has(path4)) return;
|
|
2664
|
+
registeredPaths.add(path4);
|
|
2665
|
+
app.get(path4, {
|
|
2666
|
+
websocket: true,
|
|
2667
|
+
preHandler: async (request, reply) => {
|
|
2668
|
+
const connectionId = crypto.randomUUID();
|
|
2669
|
+
request._wsConnectionId = connectionId;
|
|
2670
|
+
const connectHandlers = handlers.filter((h) => h.path === path4 && h.event === "connect");
|
|
2671
|
+
for (const h of connectHandlers) {
|
|
2672
|
+
await h.handler(connectionId, "connect", null, request, reply);
|
|
2673
|
+
}
|
|
2674
|
+
if (reply.statusCode !== 200)
|
|
2675
|
+
return reply;
|
|
2676
|
+
}
|
|
2677
|
+
}, (socket, request) => {
|
|
2678
|
+
const connectionId = request._wsConnectionId ?? crypto.randomUUID();
|
|
2679
|
+
const connection = {
|
|
2680
|
+
connectionId,
|
|
2681
|
+
socket,
|
|
2682
|
+
path: path4,
|
|
2683
|
+
connectedAt: /* @__PURE__ */ new Date()
|
|
2684
|
+
};
|
|
2685
|
+
connections.set(connectionId, connection);
|
|
2686
|
+
const pathHandlers = () => handlers.filter((h) => h.path === path4);
|
|
2687
|
+
socket.on("message", (raw) => {
|
|
2688
|
+
const data = raw.toString();
|
|
2689
|
+
const currentHandlers = pathHandlers();
|
|
2690
|
+
let routeKey;
|
|
2691
|
+
try {
|
|
2692
|
+
const parsed = JSON.parse(data);
|
|
2693
|
+
routeKey = parsed?.[config.routeKeyField];
|
|
2694
|
+
} catch {
|
|
2695
|
+
}
|
|
2696
|
+
let matched = false;
|
|
2697
|
+
if (routeKey) {
|
|
2698
|
+
const routeHandlers = currentHandlers.filter(
|
|
2699
|
+
(h) => h.event === "message" && h.route === routeKey
|
|
2700
|
+
);
|
|
2701
|
+
for (const h of routeHandlers) {
|
|
2702
|
+
matched = true;
|
|
2703
|
+
h.handler(connectionId, "message", data, request).catch((e) => {
|
|
2704
|
+
logger.error(e);
|
|
2705
|
+
});
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
if (!matched) {
|
|
2709
|
+
const defaultHandlers = currentHandlers.filter(
|
|
2710
|
+
(h) => h.event === "message" && !h.route
|
|
2711
|
+
);
|
|
2712
|
+
for (const h of defaultHandlers) {
|
|
2713
|
+
h.handler(connectionId, "message", data, request).catch((e) => {
|
|
2714
|
+
logger.error(e);
|
|
2715
|
+
});
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2718
|
+
});
|
|
2719
|
+
socket.on("close", () => {
|
|
2720
|
+
const disconnectHandlers = pathHandlers().filter((h) => h.event === "disconnect");
|
|
2721
|
+
for (const h of disconnectHandlers) {
|
|
2722
|
+
h.handler(connectionId, "disconnect", null, request).catch((e) => {
|
|
2723
|
+
logger.error(e);
|
|
2724
|
+
});
|
|
2725
|
+
}
|
|
2726
|
+
connections.delete(connectionId);
|
|
2727
|
+
});
|
|
2728
|
+
});
|
|
2729
|
+
}
|
|
2730
|
+
const manager = {
|
|
2731
|
+
registerHandler(handler) {
|
|
2732
|
+
handlers.push(handler);
|
|
2733
|
+
if (!pathModuleMap.has(handler.path)) {
|
|
2734
|
+
pathModuleMap.set(handler.path, handler.module);
|
|
2735
|
+
}
|
|
2736
|
+
ensureRouteForPath(handler.path);
|
|
2737
|
+
},
|
|
2738
|
+
getConnections(path4) {
|
|
2739
|
+
const allConnections = Array.from(connections.values());
|
|
2740
|
+
if (path4) {
|
|
2741
|
+
return allConnections.filter((c) => c.path === path4);
|
|
2742
|
+
}
|
|
2743
|
+
return allConnections;
|
|
2744
|
+
},
|
|
2745
|
+
getRegisteredPaths(module) {
|
|
2746
|
+
const all = Array.from(pathModuleMap.entries()).map(([path4, mod]) => ({ path: path4, module: mod }));
|
|
2747
|
+
if (module) {
|
|
2748
|
+
return all.filter((p) => p.module === module);
|
|
2749
|
+
}
|
|
2750
|
+
return all;
|
|
2751
|
+
},
|
|
2752
|
+
async sendToClient(connectionId, data) {
|
|
2753
|
+
const connection = connections.get(connectionId);
|
|
2754
|
+
if (!connection) {
|
|
2755
|
+
throw new Error(`WebSocket connection ${connectionId} not found`);
|
|
2756
|
+
}
|
|
2757
|
+
const payload = typeof data === "string" ? data : JSON.stringify(data);
|
|
2758
|
+
connection.socket.send(payload);
|
|
2759
|
+
},
|
|
2760
|
+
async disconnect(connectionId) {
|
|
2761
|
+
const connection = connections.get(connectionId);
|
|
2762
|
+
if (!connection) {
|
|
2763
|
+
throw new Error(`WebSocket connection ${connectionId} not found`);
|
|
2764
|
+
}
|
|
2765
|
+
connection.socket.close();
|
|
2766
|
+
}
|
|
2767
|
+
};
|
|
2768
|
+
app.decorate("websockets", manager);
|
|
2769
|
+
});
|
|
2770
|
+
|
|
2575
2771
|
// src/dev-console-plugin/route-registry.ts
|
|
2576
|
-
var RouteRegistry = class {
|
|
2772
|
+
var RouteRegistry = class _RouteRegistry {
|
|
2577
2773
|
routes = [];
|
|
2774
|
+
static IGNORED_METHODS = /* @__PURE__ */ new Set(["OPTIONS", "HEAD"]);
|
|
2578
2775
|
register(routeOptions) {
|
|
2776
|
+
const methods = Array.isArray(routeOptions.method) ? routeOptions.method : [routeOptions.method];
|
|
2777
|
+
if (methods.every((m) => _RouteRegistry.IGNORED_METHODS.has(m.toUpperCase()))) {
|
|
2778
|
+
return;
|
|
2779
|
+
}
|
|
2579
2780
|
const routeInfo = {
|
|
2580
2781
|
method: routeOptions.method,
|
|
2581
2782
|
url: routeOptions.url,
|
|
@@ -2621,17 +2822,6 @@ var LogStore = class {
|
|
|
2621
2822
|
getLogs(limit = 100) {
|
|
2622
2823
|
return this.logs.slice(0, limit);
|
|
2623
2824
|
}
|
|
2624
|
-
getLogsByLevel(level, limit = 100) {
|
|
2625
|
-
return this.logs.filter((log) => log.level === level).slice(0, limit);
|
|
2626
|
-
}
|
|
2627
|
-
getLogsByModule(module2, limit = 100) {
|
|
2628
|
-
return this.logs.filter((log) => log.module === module2).slice(0, limit);
|
|
2629
|
-
}
|
|
2630
|
-
getLogsByTrigger(triggerType, triggerName, limit = 100) {
|
|
2631
|
-
return this.logs.filter(
|
|
2632
|
-
(log) => log.triggerType === triggerType && log.trigger === triggerName
|
|
2633
|
-
).slice(0, limit);
|
|
2634
|
-
}
|
|
2635
2825
|
clear() {
|
|
2636
2826
|
this.logs = [];
|
|
2637
2827
|
}
|
|
@@ -2643,59 +2833,26 @@ var LogStore = class {
|
|
|
2643
2833
|
}
|
|
2644
2834
|
};
|
|
2645
2835
|
var logStore = new LogStore();
|
|
2646
|
-
var originalConsole = {
|
|
2647
|
-
log: console.log,
|
|
2648
|
-
error: console.error,
|
|
2649
|
-
warn: console.warn,
|
|
2650
|
-
info: console.info,
|
|
2651
|
-
debug: console.debug
|
|
2652
|
-
};
|
|
2653
|
-
var captureConsoleLog = (level, originalMethod) => {
|
|
2654
|
-
return (...args) => {
|
|
2655
|
-
originalMethod.apply(console, args);
|
|
2656
|
-
const message = args.join(" ");
|
|
2657
|
-
let source = "unknown";
|
|
2658
|
-
let module2;
|
|
2659
|
-
let trigger;
|
|
2660
|
-
let triggerType;
|
|
2661
|
-
if (message.includes("Queue") || message.includes("queue")) {
|
|
2662
|
-
source = "queue";
|
|
2663
|
-
triggerType = "queue";
|
|
2664
|
-
const queueMatch = message.match(/queue[:\s]+([a-zA-Z0-9_-]+)/i);
|
|
2665
|
-
if (queueMatch) trigger = queueMatch[1];
|
|
2666
|
-
} else if (message.includes("Schedule") || message.includes("job")) {
|
|
2667
|
-
source = "schedule";
|
|
2668
|
-
triggerType = "schedule";
|
|
2669
|
-
const jobMatch = message.match(/(?:job|schedule)[:\s]+([a-zA-Z0-9_-]+)/i);
|
|
2670
|
-
if (jobMatch) trigger = jobMatch[1];
|
|
2671
|
-
} else if (message.includes("HTTP") || message.includes("api") || message.includes("/api/")) {
|
|
2672
|
-
source = "http";
|
|
2673
|
-
triggerType = "http";
|
|
2674
|
-
const routeMatch = message.match(/\/api\/[^\s]+/);
|
|
2675
|
-
if (routeMatch) trigger = routeMatch[0];
|
|
2676
|
-
}
|
|
2677
|
-
const moduleMatch = message.match(/module[:\s]+([a-zA-Z0-9_-]+)/i) || message.match(/\[([a-zA-Z0-9_-]+)\]/) || message.match(/in\s+([a-zA-Z0-9_-]+)\s+module/i);
|
|
2678
|
-
if (moduleMatch) module2 = moduleMatch[1];
|
|
2679
|
-
logStore.addLog({
|
|
2680
|
-
id: Date.now().toString() + Math.random().toString(36).substr(2, 9),
|
|
2681
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
2682
|
-
level,
|
|
2683
|
-
message: message.replace(/\x1b\[[0-9;]*m/g, ""),
|
|
2684
|
-
// Remove ANSI colors
|
|
2685
|
-
source,
|
|
2686
|
-
module: module2,
|
|
2687
|
-
trigger,
|
|
2688
|
-
triggerType
|
|
2689
|
-
});
|
|
2690
|
-
};
|
|
2691
|
-
};
|
|
2692
|
-
console.error = captureConsoleLog("error", originalConsole.error);
|
|
2693
|
-
console.warn = captureConsoleLog("warn", originalConsole.warn);
|
|
2694
|
-
console.info = captureConsoleLog("info", originalConsole.info);
|
|
2695
|
-
console.log = captureConsoleLog("info", originalConsole.log);
|
|
2696
|
-
console.debug = captureConsoleLog("debug", originalConsole.debug);
|
|
2697
2836
|
async function devConsolePluginFunction(fastify, options = {}) {
|
|
2698
2837
|
const { prefix = "console", enableUI = true } = options;
|
|
2838
|
+
const upstream = getWriter();
|
|
2839
|
+
setWriter((entry) => {
|
|
2840
|
+
logStore.addLog({
|
|
2841
|
+
id: Date.now().toString() + Math.random().toString(36).slice(2, 9),
|
|
2842
|
+
timestamp: new Date(entry.time),
|
|
2843
|
+
levelName: entry.levelName,
|
|
2844
|
+
message: entry.msg,
|
|
2845
|
+
meta: entry.meta,
|
|
2846
|
+
module: entry.module,
|
|
2847
|
+
reqId: entry.reqId
|
|
2848
|
+
});
|
|
2849
|
+
upstream(entry);
|
|
2850
|
+
});
|
|
2851
|
+
fastify.addHook("onClose", (_instance, done) => {
|
|
2852
|
+
setWriter(upstream);
|
|
2853
|
+
logStore.clear();
|
|
2854
|
+
done();
|
|
2855
|
+
});
|
|
2699
2856
|
fastify.addHook("onRoute", (routeOptions) => {
|
|
2700
2857
|
if (routeOptions.prefix === "/api") {
|
|
2701
2858
|
routeRegistry.register(routeOptions);
|
|
@@ -2717,7 +2874,8 @@ async function devConsolePluginFunction(fastify, options = {}) {
|
|
|
2717
2874
|
fastify.get(`/${prefix}/modules`, async (_, reply) => {
|
|
2718
2875
|
const queueManager = fastify.queues;
|
|
2719
2876
|
const schedulerManager = fastify.scheduler;
|
|
2720
|
-
|
|
2877
|
+
const wsManager = fastify.websockets;
|
|
2878
|
+
if (!queueManager || !schedulerManager || !wsManager) {
|
|
2721
2879
|
return reply.status(503).send({ error: "Services not available" });
|
|
2722
2880
|
}
|
|
2723
2881
|
const allRoutes = routeRegistry.getAll();
|
|
@@ -2736,6 +2894,9 @@ async function devConsolePluginFunction(fastify, options = {}) {
|
|
|
2736
2894
|
const jobStats = schedulerManager.getJobStats(jobName);
|
|
2737
2895
|
if (jobStats?.job.module) moduleSet.add(jobStats.job.module);
|
|
2738
2896
|
});
|
|
2897
|
+
wsManager.getRegisteredPaths().forEach((p) => {
|
|
2898
|
+
if (p.module) moduleSet.add(p.module);
|
|
2899
|
+
});
|
|
2739
2900
|
const modules = Array.from(moduleSet).map((moduleName) => {
|
|
2740
2901
|
const moduleRoutes = httpRoutes.filter((route) => route.module === moduleName);
|
|
2741
2902
|
const moduleQueueNames = queueManager.listQueues(moduleName);
|
|
@@ -2761,11 +2922,16 @@ async function devConsolePluginFunction(fastify, options = {}) {
|
|
|
2761
2922
|
timezone: jobStats?.job.timezone
|
|
2762
2923
|
};
|
|
2763
2924
|
});
|
|
2925
|
+
const moduleWebSockets = wsManager ? wsManager.getRegisteredPaths(moduleName).map((p) => ({
|
|
2926
|
+
path: p.path,
|
|
2927
|
+
connectionCount: wsManager.getConnections(p.path).length
|
|
2928
|
+
})) : [];
|
|
2764
2929
|
return {
|
|
2765
2930
|
name: moduleName,
|
|
2766
2931
|
routes: moduleRoutes,
|
|
2767
2932
|
queues: moduleQueues,
|
|
2768
|
-
schedules: moduleSchedules
|
|
2933
|
+
schedules: moduleSchedules,
|
|
2934
|
+
websockets: moduleWebSockets
|
|
2769
2935
|
};
|
|
2770
2936
|
});
|
|
2771
2937
|
return { modules };
|
|
@@ -2883,7 +3049,7 @@ async function devConsolePluginFunction(fastify, options = {}) {
|
|
|
2883
3049
|
}
|
|
2884
3050
|
});
|
|
2885
3051
|
fastify.post(`/${prefix}/queues`, async (request, reply) => {
|
|
2886
|
-
const { queueName, module
|
|
3052
|
+
const { queueName, module } = request.body;
|
|
2887
3053
|
const queueManager = fastify.queues;
|
|
2888
3054
|
if (!queueManager) {
|
|
2889
3055
|
return reply.status(503).send({ error: "Queue service not available" });
|
|
@@ -2894,8 +3060,9 @@ async function devConsolePluginFunction(fastify, options = {}) {
|
|
|
2894
3060
|
try {
|
|
2895
3061
|
const handler = async (message) => {
|
|
2896
3062
|
console.log(`Processing message in ${queueName}:`, message);
|
|
3063
|
+
return void 0;
|
|
2897
3064
|
};
|
|
2898
|
-
await queueManager.addQueue(queueName, handler,
|
|
3065
|
+
await queueManager.addQueue(queueName, handler, module);
|
|
2899
3066
|
return reply.status(201).send({
|
|
2900
3067
|
status: "success",
|
|
2901
3068
|
message: `Queue ${queueName} created successfully`,
|
|
@@ -2995,27 +3162,18 @@ async function devConsolePluginFunction(fastify, options = {}) {
|
|
|
2995
3162
|
const {
|
|
2996
3163
|
limit = 100,
|
|
2997
3164
|
level,
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
trigger,
|
|
3001
|
-
triggerType
|
|
3165
|
+
module,
|
|
3166
|
+
reqId
|
|
3002
3167
|
} = request.query;
|
|
3003
3168
|
let logs = logStore.getLogs(Number(limit));
|
|
3004
3169
|
if (level) {
|
|
3005
|
-
logs = logs.filter((log) => log.
|
|
3170
|
+
logs = logs.filter((log) => log.levelName === level);
|
|
3006
3171
|
}
|
|
3007
|
-
if (
|
|
3008
|
-
logs = logs.filter((log) => log.
|
|
3172
|
+
if (module) {
|
|
3173
|
+
logs = logs.filter((log) => log.module === module);
|
|
3009
3174
|
}
|
|
3010
|
-
if (
|
|
3011
|
-
logs = logs.filter(
|
|
3012
|
-
(log) => log.module === module2 || log.message.toLowerCase().includes(module2.toLowerCase())
|
|
3013
|
-
);
|
|
3014
|
-
}
|
|
3015
|
-
if (trigger && triggerType) {
|
|
3016
|
-
logs = logs.filter(
|
|
3017
|
-
(log) => log.trigger === trigger && log.triggerType === triggerType || log.message.toLowerCase().includes(trigger.toLowerCase())
|
|
3018
|
-
);
|
|
3175
|
+
if (reqId) {
|
|
3176
|
+
logs = logs.filter((log) => log.reqId === reqId);
|
|
3019
3177
|
}
|
|
3020
3178
|
return { logs };
|
|
3021
3179
|
});
|
|
@@ -3023,6 +3181,50 @@ async function devConsolePluginFunction(fastify, options = {}) {
|
|
|
3023
3181
|
logStore.clear();
|
|
3024
3182
|
return { status: "success", message: "Logs cleared" };
|
|
3025
3183
|
});
|
|
3184
|
+
fastify.get(`/${prefix}/websockets`, async (_, reply) => {
|
|
3185
|
+
const wsManager = fastify.websockets;
|
|
3186
|
+
if (!wsManager) {
|
|
3187
|
+
return reply.status(503).send({ error: "WebSocket service not available" });
|
|
3188
|
+
}
|
|
3189
|
+
const connections = wsManager.getConnections();
|
|
3190
|
+
const pathSet = new Set(connections.map((c) => c.path));
|
|
3191
|
+
const paths = Array.from(pathSet).map((p) => ({
|
|
3192
|
+
path: p,
|
|
3193
|
+
connections: wsManager.getConnections(p).map((c) => ({
|
|
3194
|
+
connectionId: c.connectionId,
|
|
3195
|
+
path: c.path,
|
|
3196
|
+
connectedAt: c.connectedAt
|
|
3197
|
+
}))
|
|
3198
|
+
}));
|
|
3199
|
+
return { paths };
|
|
3200
|
+
});
|
|
3201
|
+
fastify.get(`/${prefix}/websockets/:path`, async (request, reply) => {
|
|
3202
|
+
const wsManager = fastify.websockets;
|
|
3203
|
+
if (!wsManager) {
|
|
3204
|
+
return reply.status(503).send({ error: "WebSocket service not available" });
|
|
3205
|
+
}
|
|
3206
|
+
const { path: wsPath } = request.params;
|
|
3207
|
+
const decodedPath = "/" + wsPath;
|
|
3208
|
+
const connections = wsManager.getConnections(decodedPath).map((c) => ({
|
|
3209
|
+
connectionId: c.connectionId,
|
|
3210
|
+
path: c.path,
|
|
3211
|
+
connectedAt: c.connectedAt
|
|
3212
|
+
}));
|
|
3213
|
+
return { path: decodedPath, connections };
|
|
3214
|
+
});
|
|
3215
|
+
fastify.post(`/${prefix}/websockets/:connectionId/send`, async (request, reply) => {
|
|
3216
|
+
const wsManager = fastify.websockets;
|
|
3217
|
+
if (!wsManager) {
|
|
3218
|
+
return reply.status(503).send({ error: "WebSocket service not available" });
|
|
3219
|
+
}
|
|
3220
|
+
const { connectionId } = request.params;
|
|
3221
|
+
try {
|
|
3222
|
+
await wsManager.sendToClient(connectionId, request.body);
|
|
3223
|
+
return reply.status(200).send({ status: "success", message: `Message sent to ${connectionId}` });
|
|
3224
|
+
} catch (error) {
|
|
3225
|
+
return reply.status(404).send({ error: error.message });
|
|
3226
|
+
}
|
|
3227
|
+
});
|
|
3026
3228
|
fastify.get(`/${prefix}/logs/stream`, async (request, reply) => {
|
|
3027
3229
|
reply.type("text/event-stream");
|
|
3028
3230
|
reply.header("Cache-Control", "no-cache");
|
|
@@ -3047,14 +3249,15 @@ async function devConsolePluginFunction(fastify, options = {}) {
|
|
|
3047
3249
|
);
|
|
3048
3250
|
await fastify.register(fastifyStatic, {
|
|
3049
3251
|
root: devConsolePath,
|
|
3050
|
-
decorateReply: true
|
|
3252
|
+
decorateReply: true,
|
|
3253
|
+
prefix: `/${prefix}/`
|
|
3051
3254
|
});
|
|
3052
3255
|
fastify.get(`/${prefix}`, async (_, reply) => {
|
|
3053
3256
|
return reply.sendFile("index.html");
|
|
3054
3257
|
});
|
|
3055
3258
|
}
|
|
3056
3259
|
}
|
|
3057
|
-
var devConsolePlugin =
|
|
3260
|
+
var devConsolePlugin = fsPlugin4(devConsolePluginFunction, {
|
|
3058
3261
|
name: "dev-console-plugin"
|
|
3059
3262
|
});
|
|
3060
3263
|
export {
|