@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.
@@ -1,4 +1,5 @@
1
1
  import { FastifyPluginOptions, FastifyPluginAsync } from 'fastify';
2
+ import { EventBatchItemResult } from '@cloudnux/core-cloud-provider';
2
3
 
3
4
  interface QueueMessage {
4
5
  id: string;
@@ -12,7 +13,7 @@ interface QueueMessage {
12
13
  reprocessed?: boolean;
13
14
  originalId?: string;
14
15
  }
15
- type EventHandler = (message: QueueMessage) => Promise<void>;
16
+ type EventHandler = (message: QueueMessage) => Promise<EventBatchItemResult>;
16
17
  interface QueueService {
17
18
  handler: EventHandler;
18
19
  incoming: QueueMessage[];
@@ -1,9 +1,6 @@
1
- // src/queue-plugin/plugin.ts
2
- import fsPlugin from "fastify-plugin";
3
-
4
- // src/queue-plugin/core.ts
5
- import chalk2 from "chalk";
6
- import logSymbols from "log-symbols";
1
+ // src/logging/pretty-writer.ts
2
+ import chalk from "chalk";
3
+ import { EOL as EOL2 } from "os";
7
4
 
8
5
  // ../../../node_modules/lodash-es/_freeGlobal.js
9
6
  var freeGlobal = typeof global == "object" && global && global.Object === Object && global;
@@ -827,20 +824,32 @@ var utils = {
827
824
  };
828
825
  var env = Object.assign(_env, utils);
829
826
 
830
- // ../../utils/src/logging/index.ts
831
- import chalk from "chalk";
832
- import { EOL } from "os";
833
-
834
827
  // ../../utils/src/logging/types.ts
835
828
  var logLevels = {
836
829
  fatal: -1,
837
830
  error: 0,
838
831
  warn: 1,
839
832
  info: 2,
840
- debug: 3
833
+ debug: 3,
834
+ trace: 4
841
835
  };
842
836
 
843
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
+ };
844
853
  var errorToString = (error) => {
845
854
  if (error === null) return "Null error";
846
855
  if (error === void 0) return "Undefined error";
@@ -850,13 +859,22 @@ var errorToString = (error) => {
850
859
  `Message: ${error.message}`,
851
860
  `Stack: ${error.stack || "No stack trace available"}`,
852
861
  // Handle additional properties that might exist on custom errors
853
- ...Object.entries(error).filter(([key]) => !["name", "message", "stack"].includes(key)).map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
862
+ ...Object.entries(error).filter(
863
+ ([key, value]) => !["name", "message", "stack"].includes(key) && !hasOwnConstructorProp(value)
864
+ ).map(([key, value]) => `${key}: ${safeJsonStringify(value)}`)
854
865
  ].join("\n");
855
866
  }
856
867
  if (typeof error === "string") return error;
857
868
  if (typeof error === "object") {
858
869
  try {
859
- return JSON.stringify(error, null, 2);
870
+ return JSON.stringify(
871
+ error,
872
+ (key, value) => {
873
+ if (key === "constructor") return void 0;
874
+ return value;
875
+ },
876
+ 2
877
+ );
860
878
  } catch {
861
879
  return `[Object that cannot be stringified: ${Object.prototype.toString.call(error)}]`;
862
880
  }
@@ -864,62 +882,130 @@ var errorToString = (error) => {
864
882
  return String(error);
865
883
  };
866
884
 
885
+ // ../../utils/src/logging/writer.ts
886
+ import { EOL } from "os";
887
+ var jsonWriter = (entry) => {
888
+ process.stdout.write(JSON.stringify(entry) + EOL);
889
+ };
890
+ var _writer = jsonWriter;
891
+ function setWriter(writer) {
892
+ _writer = writer;
893
+ }
894
+ function getWriter() {
895
+ return _writer;
896
+ }
897
+
867
898
  // ../../utils/src/logging/index.ts
868
- var currentLogLevel = logLevels[env("LOG_LEVEL")?.toLowerCase()] ?? logLevels.info;
869
- var module = "default";
870
- var requestId = "";
871
- var logger = {
872
- fatal: (message, meta) => {
873
- if (currentLogLevel >= logLevels.fatal) {
874
- console.error(
875
- `[${(/* @__PURE__ */ new Date()).toTimeString()}]`,
876
- `${chalk.bgRed.white(" fatal ")} - ${module || "unknown module"} - ${requestId || "no request ID"} - ${EOL}`,
877
- errorToString(message),
878
- meta ? `${EOL}${JSON.stringify(meta, null, 2)}` : ""
879
- );
880
- }
881
- },
882
- error: (message, meta) => {
883
- if (currentLogLevel >= logLevels.error) {
884
- console.error(
885
- `[${(/* @__PURE__ */ new Date()).toTimeString()}]`,
886
- `${chalk.bgRed.white(" error ")} - ${module || "unknown module"} - ${requestId || "no request ID"} - ${EOL}`,
887
- errorToString(message),
888
- meta ? `${EOL}${JSON.stringify(meta, null, 2)}` : ""
889
- );
890
- }
891
- },
892
- warn: (message, meta) => {
893
- if (currentLogLevel >= logLevels.warn) {
894
- console.warn(
895
- `[${(/* @__PURE__ */ new Date()).toTimeString()}]`,
896
- `${chalk.bgYellow.black(" warn ")} - ${module || "unknown module"} - ${requestId || "no request ID"} - ${EOL}`,
897
- errorToString(message),
898
- meta ? `${EOL}${JSON.stringify(meta, null, 2)}` : ""
899
- );
900
- }
901
- },
902
- info: (message, meta) => {
903
- if (currentLogLevel >= logLevels.info) {
904
- console.info(
905
- `[${(/* @__PURE__ */ new Date()).toTimeString()}]`,
906
- `${chalk.bgBlue.white(" info ")} - ${module || "unknown module"} - ${requestId || "no request ID"} - ${EOL}`,
907
- message,
908
- meta ? `${EOL}${JSON.stringify(meta, null, 2)}` : ""
909
- );
910
- }
911
- },
912
- debug: (message, meta) => {
913
- if (currentLogLevel >= logLevels.debug) {
914
- console.debug(
915
- `[${(/* @__PURE__ */ new Date()).toTimeString()}]`,
916
- `${chalk.bgWhite.black(" debug ")} - ${module || "unknown module"} - ${requestId || "no request ID"} - ${EOL}`,
917
- message,
918
- meta ? `${EOL}${JSON.stringify(meta, null, 2)}` : ""
919
- );
920
- }
921
- }
899
+ var levelValues = {
900
+ fatal: 70,
901
+ error: 60,
902
+ warn: 50,
903
+ info: 40,
904
+ debug: 30,
905
+ trace: 20
922
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/queue-plugin/plugin.ts
1008
+ import fsPlugin from "fastify-plugin";
923
1009
 
924
1010
  // src/queue-plugin/core.ts
925
1011
  var DEFAULT_CONFIG = {
@@ -945,14 +1031,14 @@ var mergeConfig = (defaultConfig, userConfig) => ({
945
1031
  ...userConfig?.persistence || {}
946
1032
  }
947
1033
  });
948
- var createQueueService = (handler, module2) => ({
1034
+ var createQueueService = (handler, module) => ({
949
1035
  handler,
950
1036
  incoming: [],
951
1037
  processing: [],
952
1038
  dlq: [],
953
1039
  timeoutId: null,
954
1040
  processingBatch: false,
955
- module: module2
1041
+ module
956
1042
  });
957
1043
  var createQueueMessage = (body, headers) => {
958
1044
  const id = Date.now().toString() + Math.random().toString(36).substring(2, 7);
@@ -1033,32 +1119,36 @@ var purgeDLQ = (queueService) => {
1033
1119
  return dlqCount;
1034
1120
  };
1035
1121
  var logSuccess = (message, messageId, queueName) => {
1036
- logger.debug(`${logSymbols.success} ${chalk2.green(message)} ${chalk2.yellow(messageId)} in queue ${chalk2.magenta(queueName)}`);
1122
+ logger.debug(`Success: ${message} ${messageId} in queue ${queueName}`);
1037
1123
  };
1038
1124
  var logError = (message, messageId, queueName, error) => {
1039
- logger.error(`${logSymbols.error} ${chalk2.red(message)} ${chalk2.yellow(messageId)} in queue ${chalk2.magenta(queueName)}: ${error}`);
1125
+ logger.error(`Error: ${message} ${messageId} in queue ${queueName}: ${error}`);
1040
1126
  };
1041
1127
  var logRetryScheduled = (messageId, delayMs) => {
1042
- logger.debug(`${chalk2.blue("\u23F1\uFE0F Scheduling retry")} for message ${chalk2.yellow(messageId)} in ${chalk2.cyan(delayMs)}ms`);
1128
+ logger.debug(`Scheduling retry for message ${messageId} in ${delayMs}ms`);
1043
1129
  };
1044
1130
  var logDLQOperation = (operation, count, queueName) => {
1045
- logger.warn(`${logSymbols.warning} ${chalk2.yellow(operation)} ${chalk2.red(count)} messages from DLQ for ${chalk2.green(queueName)}`);
1131
+ logger.warn(`${operation} ${count} messages from DLQ for ${queueName}`);
1046
1132
  };
1047
1133
 
1048
1134
  // src/queue-plugin/processing.ts
1049
1135
  var createProcessMessageHandler = (config) => async (queueName, message, queueService) => {
1050
1136
  try {
1051
- await queueService.handler(message);
1052
- removeFromProcessing(queueService, message.id);
1053
- logSuccess("Successfully processed message", message.id, queueName);
1054
- } catch (error) {
1055
- await handleProcessingError(queueName, message, queueService, error, config);
1137
+ const result = await queueService.handler(message);
1138
+ if (result?.failureId) {
1139
+ await handleProcessingError(queueName, message, queueService, config);
1140
+ } else {
1141
+ removeFromProcessing(queueService, message.id);
1142
+ logSuccess("Successfully processed message", message.id, queueName);
1143
+ }
1144
+ } catch {
1145
+ await handleProcessingError(queueName, message, queueService, config);
1056
1146
  }
1057
1147
  };
1058
- var handleProcessingError = async (queueName, message, queueService, error, config) => {
1059
- logError("Error processing message", message.id, queueName, error.message);
1148
+ var handleProcessingError = async (queueName, message, queueService, config) => {
1149
+ logError("Error processing message", message.id, queueName, "handler returned failure");
1060
1150
  if (message.attempts >= config.maxRetries) {
1061
- moveToDLQ(queueService, message, error.message);
1151
+ moveToDLQ(queueService, message, "max retries exceeded");
1062
1152
  return;
1063
1153
  }
1064
1154
  const updatedMessage = incrementAttempts(queueService, message.id);
@@ -1118,8 +1208,6 @@ var handleImmediateProcessing = (queueService, config, processBatch, queueName)
1118
1208
  // src/queue-plugin/persistence.ts
1119
1209
  import * as fs from "fs/promises";
1120
1210
  import * as path from "path";
1121
- import chalk3 from "chalk";
1122
- import logSymbols2 from "log-symbols";
1123
1211
  var createQueueData = (queueService) => ({
1124
1212
  incoming: queueService.incoming,
1125
1213
  processing: queueService.processing,
@@ -1154,10 +1242,9 @@ var createPersistenceInitializer = (config, loadAllQueueStates, saveDirtyQueueSt
1154
1242
  process.on("SIGINT", shutdownHandler);
1155
1243
  process.on("SIGTERM", shutdownHandler);
1156
1244
  }
1157
- logger.debug(`${logSymbols2.success} ${chalk3.green("Queue persistence initialized:")} ${chalk3.yellow(config.persistence.directory)}`);
1245
+ logger.debug(`Queue persistence initialized: ${config.persistence.directory}`);
1158
1246
  } catch (error) {
1159
- console.log("[logger]", logger);
1160
- logger.error(`${logSymbols2.error} ${chalk3.red("Failed to initialize queue persistence:")} ${chalk3.yellow(error?.message)}`);
1247
+ logger.error(`Failed to initialize queue persistence: ${error?.message}`);
1161
1248
  }
1162
1249
  };
1163
1250
  var createQueueStateSaver = (config) => async (queueName, queueService) => {
@@ -1169,7 +1256,7 @@ var createQueueStateSaver = (config) => async (queueName, queueService) => {
1169
1256
  const tempFilePath = path.join(config.persistence.directory, `${queueName}.${now}temp.json`);
1170
1257
  await fs.writeFile(tempFilePath, JSON.stringify(queueData, null, 2), "utf8");
1171
1258
  await fs.rename(tempFilePath, queueFilePath);
1172
- logger.debug(`${logSymbols2.info} ${chalk3.blue("Queue state saved:")} ${chalk3.green(queueName)}`);
1259
+ logger.debug(`Queue state saved: ${queueName}`);
1173
1260
  } catch (error) {
1174
1261
  logger.error(`Failed to save queue state for ${queueName}:`, error?.message);
1175
1262
  }
@@ -1179,9 +1266,9 @@ var createAllQueuesStateSaver = (config, saveQueueState) => (queues) => async ()
1179
1266
  for (const [queueName, queueService] of Object.entries(queues)) {
1180
1267
  await saveQueueState(queueName, queueService);
1181
1268
  }
1182
- logger.debug(`${logSymbols2.success} ${chalk3.green("All queue states saved to")} ${chalk3.yellow(config.persistence.directory)}`);
1269
+ logger.debug(`All queue states saved to ${config.persistence.directory}`);
1183
1270
  } catch (error) {
1184
- logger.error(`${logSymbols2.error} ${chalk3.red("Failed to save all queue states:")} ${chalk3.yellow(error?.message)}`);
1271
+ logger.error(`Failed to save all queue states: ${error?.message}`);
1185
1272
  }
1186
1273
  };
1187
1274
  var createDirtyQueuesStateSaver = (saveQueueState, dirtyQueues) => (queues) => async () => {
@@ -1195,7 +1282,7 @@ var createDirtyQueuesStateSaver = (saveQueueState, dirtyQueues) => (queues) => a
1195
1282
  }
1196
1283
  }
1197
1284
  } catch (error) {
1198
- logger.error(`${logSymbols2.error} ${chalk3.red("Failed to save dirty queue states:")} ${chalk3.yellow(error?.message)}`);
1285
+ logger.error(`Failed to save dirty queue states: ${error?.message}`);
1199
1286
  }
1200
1287
  };
1201
1288
  var createQueueStateLoader = (config, scheduleProcessing, processMessage) => (queues) => async (queueName) => {
@@ -1307,8 +1394,6 @@ var registerQueueRoutes = (app, prefix = "") => {
1307
1394
  };
1308
1395
 
1309
1396
  // src/queue-plugin/decorator.ts
1310
- import chalk4 from "chalk";
1311
- import logSymbols3 from "log-symbols";
1312
1397
  var isValidQueueName = (queueName) => {
1313
1398
  return typeof queueName === "string" && queueName.length > 0 && /^[a-zA-Z0-9_-]+$/.test(queueName);
1314
1399
  };
@@ -1334,21 +1419,21 @@ var createQueueManager = ({
1334
1419
  throw new Error("Handler must be a function");
1335
1420
  }
1336
1421
  };
1337
- const addQueue = async (queueName, handler, module2) => {
1422
+ const addQueue = async (queueName, handler, module) => {
1338
1423
  try {
1339
1424
  validateQueueName(queueName);
1340
1425
  validateHandler(handler);
1341
1426
  if (queues[queueName]) {
1342
- logger.warn(`${logSymbols3.warning} ${chalk4.yellow("Queue already exists:")} ${chalk4.magenta(queueName)}.`);
1427
+ logger.warn(`Queue already exists: ${queueName}.`);
1343
1428
  return;
1344
1429
  }
1345
- queues[queueName] = createQueueService(handler, module2);
1430
+ queues[queueName] = createQueueService(handler, module);
1346
1431
  if (config.persistence.enabled && loadQueueState) {
1347
1432
  await loadQueueState(queueName);
1348
1433
  }
1349
- logger.info(`${logSymbols3.success} ${chalk4.green("Queue added:")} ${chalk4.magenta(queueName)}`);
1434
+ logger.info(`Queue added: ${queueName}`);
1350
1435
  } catch (error) {
1351
- logger.error(`${logSymbols3.error} ${chalk4.red("Failed to add queue")} ${chalk4.magenta(queueName)}: ${error.message}`);
1436
+ logger.error(`Failed to add queue ${queueName}: ${error.message}`);
1352
1437
  throw error;
1353
1438
  }
1354
1439
  };
@@ -1361,7 +1446,7 @@ var createQueueManager = ({
1361
1446
  const queueService = queues[queueName];
1362
1447
  const totalMessages = queueService.incoming.length + queueService.processing.length;
1363
1448
  if (totalMessages > 0) {
1364
- logger.warn(`${logSymbols3.warning} ${chalk4.yellow("Removing queue with")} ${chalk4.red(totalMessages)} ${chalk4.yellow("pending messages:")} ${chalk4.magenta(queueName)}`);
1449
+ logger.warn(`Removing queue with ${totalMessages} pending messages: ${queueName}`);
1365
1450
  }
1366
1451
  if (queueService.timeoutId) {
1367
1452
  clearTimeout(queueService.timeoutId);
@@ -1370,9 +1455,9 @@ var createQueueManager = ({
1370
1455
  await saveQueueState(queueName, queueService);
1371
1456
  }
1372
1457
  delete queues[queueName];
1373
- logger.info(`${logSymbols3.success} ${chalk4.green("Queue removed:")} ${chalk4.magenta(queueName)}`);
1458
+ logger.info(`Queue removed: ${queueName}`);
1374
1459
  } catch (error) {
1375
- logger.error(`${logSymbols3.error} ${chalk4.red("Failed to remove queue")} ${chalk4.magenta(queueName)}: ${error.message}`);
1460
+ logger.error(`Failed to remove queue ${queueName}: ${error.message}`);
1376
1461
  throw error;
1377
1462
  }
1378
1463
  };
@@ -1384,10 +1469,10 @@ var createQueueManager = ({
1384
1469
  return false;
1385
1470
  }
1386
1471
  };
1387
- const listQueues = (module2) => {
1472
+ const listQueues = (module) => {
1388
1473
  return Object.keys(queues).filter((queueName) => {
1389
1474
  const queueService = queues[queueName];
1390
- return !module2 || queueService.module === module2;
1475
+ return !module || queueService.module === module;
1391
1476
  }).sort();
1392
1477
  };
1393
1478
  const getQueueStats = (queueName) => {