@camstack/core 0.1.14 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +220 -0
  2. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js.map +1 -0
  3. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +9 -0
  4. package/dist/builtins/addon-pages-aggregator/index.js +222 -0
  5. package/dist/builtins/addon-pages-aggregator/index.js.map +1 -0
  6. package/dist/builtins/addon-pages-aggregator/index.mjs +9 -0
  7. package/dist/builtins/addon-pages-aggregator/index.mjs.map +1 -0
  8. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +200 -0
  9. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js.map +1 -0
  10. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +9 -0
  11. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs.map +1 -0
  12. package/dist/builtins/addon-widgets-aggregator/index.js +202 -0
  13. package/dist/builtins/addon-widgets-aggregator/index.js.map +1 -0
  14. package/dist/builtins/addon-widgets-aggregator/index.mjs +9 -0
  15. package/dist/builtins/addon-widgets-aggregator/index.mjs.map +1 -0
  16. package/dist/builtins/alerts/alerts.addon.js +443 -0
  17. package/dist/builtins/alerts/alerts.addon.js.map +1 -0
  18. package/dist/builtins/alerts/alerts.addon.mjs +9 -0
  19. package/dist/builtins/alerts/alerts.addon.mjs.map +1 -0
  20. package/dist/builtins/alerts/index.js +443 -0
  21. package/dist/builtins/alerts/index.js.map +1 -0
  22. package/dist/builtins/alerts/index.mjs +8 -0
  23. package/dist/builtins/alerts/index.mjs.map +1 -0
  24. package/dist/builtins/console-logging/index.js +242 -0
  25. package/dist/builtins/console-logging/index.js.map +1 -0
  26. package/dist/builtins/console-logging/index.mjs +11 -0
  27. package/dist/builtins/console-logging/index.mjs.map +1 -0
  28. package/dist/builtins/device-manager/device-manager.addon.js +2155 -0
  29. package/dist/builtins/device-manager/device-manager.addon.js.map +1 -0
  30. package/dist/builtins/device-manager/device-manager.addon.mjs +9 -0
  31. package/dist/builtins/device-manager/device-manager.addon.mjs.map +1 -0
  32. package/dist/builtins/device-manager/index.js +2157 -0
  33. package/dist/builtins/device-manager/index.js.map +1 -0
  34. package/dist/builtins/device-manager/index.mjs +10 -0
  35. package/dist/builtins/device-manager/index.mjs.map +1 -0
  36. package/dist/builtins/hub-forwarder/index.js +297 -0
  37. package/dist/builtins/hub-forwarder/index.js.map +1 -0
  38. package/dist/builtins/hub-forwarder/index.mjs +11 -0
  39. package/dist/builtins/hub-forwarder/index.mjs.map +1 -0
  40. package/dist/builtins/local-auth/index.js +623 -0
  41. package/dist/builtins/local-auth/index.js.map +1 -0
  42. package/dist/builtins/local-auth/index.mjs +8 -0
  43. package/dist/builtins/local-auth/index.mjs.map +1 -0
  44. package/dist/builtins/local-auth/local-auth.addon.js +623 -0
  45. package/dist/builtins/local-auth/local-auth.addon.js.map +1 -0
  46. package/dist/builtins/local-auth/local-auth.addon.mjs +9 -0
  47. package/dist/builtins/local-auth/local-auth.addon.mjs.map +1 -0
  48. package/dist/builtins/local-backup/index.js +53 -68
  49. package/dist/builtins/local-backup/index.js.map +1 -1
  50. package/dist/builtins/local-backup/index.mjs +1 -1
  51. package/dist/builtins/native-metrics/native-metrics.addon.js +898 -0
  52. package/dist/builtins/native-metrics/native-metrics.addon.js.map +1 -0
  53. package/dist/builtins/native-metrics/native-metrics.addon.mjs +7 -0
  54. package/dist/builtins/native-metrics/native-metrics.addon.mjs.map +1 -0
  55. package/dist/builtins/snapshot/index.js +504 -0
  56. package/dist/builtins/snapshot/index.js.map +1 -0
  57. package/dist/builtins/snapshot/index.mjs +477 -0
  58. package/dist/builtins/snapshot/index.mjs.map +1 -0
  59. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +16 -166
  60. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js.map +1 -1
  61. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  62. package/dist/builtins/sqlite-storage/index.js +554 -621
  63. package/dist/builtins/sqlite-storage/index.js.map +1 -1
  64. package/dist/builtins/sqlite-storage/index.mjs +9 -11
  65. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +368 -130
  66. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js.map +1 -1
  67. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
  68. package/dist/builtins/system-config/index.js +189 -0
  69. package/dist/builtins/system-config/index.js.map +1 -0
  70. package/dist/builtins/system-config/index.mjs +10 -0
  71. package/dist/builtins/system-config/index.mjs.map +1 -0
  72. package/dist/builtins/system-config/system-config.addon.js +187 -0
  73. package/dist/builtins/system-config/system-config.addon.js.map +1 -0
  74. package/dist/builtins/system-config/system-config.addon.mjs +9 -0
  75. package/dist/builtins/system-config/system-config.addon.mjs.map +1 -0
  76. package/dist/builtins/winston-logging/index.js +185 -65
  77. package/dist/builtins/winston-logging/index.js.map +1 -1
  78. package/dist/builtins/winston-logging/index.mjs +2 -1
  79. package/dist/chunk-2CIYKDRN.mjs +1 -0
  80. package/dist/chunk-2CIYKDRN.mjs.map +1 -0
  81. package/dist/chunk-2F76X6NL.mjs +136 -0
  82. package/dist/chunk-2F76X6NL.mjs.map +1 -0
  83. package/dist/chunk-2QUFBZ7M.mjs +1 -0
  84. package/dist/chunk-2QUFBZ7M.mjs.map +1 -0
  85. package/dist/chunk-3BK2Y7GY.mjs +593 -0
  86. package/dist/chunk-3BK2Y7GY.mjs.map +1 -0
  87. package/dist/chunk-4OOHFJHT.mjs +421 -0
  88. package/dist/chunk-4OOHFJHT.mjs.map +1 -0
  89. package/dist/chunk-4XHB7IHT.mjs +809 -0
  90. package/dist/chunk-4XHB7IHT.mjs.map +1 -0
  91. package/dist/{chunk-2F3XZYRW.mjs → chunk-6M2HSSTQ.mjs} +16 -7
  92. package/dist/chunk-6M2HSSTQ.mjs.map +1 -0
  93. package/dist/{chunk-SO4LROOT.mjs → chunk-7FI7SQS7.mjs} +54 -69
  94. package/dist/chunk-7FI7SQS7.mjs.map +1 -0
  95. package/dist/chunk-ED57RCQE.mjs +171 -0
  96. package/dist/chunk-ED57RCQE.mjs.map +1 -0
  97. package/dist/chunk-FZN56HGQ.mjs +626 -0
  98. package/dist/chunk-FZN56HGQ.mjs.map +1 -0
  99. package/dist/chunk-GL4OOB25.mjs +51 -0
  100. package/dist/chunk-GL4OOB25.mjs.map +1 -0
  101. package/dist/chunk-KDG2NTDB.mjs +137 -0
  102. package/dist/chunk-KDG2NTDB.mjs.map +1 -0
  103. package/dist/chunk-NRBQWBDM.mjs +191 -0
  104. package/dist/chunk-NRBQWBDM.mjs.map +1 -0
  105. package/dist/chunk-O4V246GG.mjs +2137 -0
  106. package/dist/chunk-O4V246GG.mjs.map +1 -0
  107. package/dist/chunk-QT57H266.mjs +163 -0
  108. package/dist/chunk-QT57H266.mjs.map +1 -0
  109. package/dist/chunk-QX4RH25I.mjs +141 -0
  110. package/dist/chunk-QX4RH25I.mjs.map +1 -0
  111. package/dist/chunk-TB562PZX.mjs +86 -0
  112. package/dist/chunk-TB562PZX.mjs.map +1 -0
  113. package/dist/chunk-TDYPZXK5.mjs +1 -0
  114. package/dist/chunk-TDYPZXK5.mjs.map +1 -0
  115. package/dist/chunk-UJI4LN5P.mjs +36 -0
  116. package/dist/chunk-UJI4LN5P.mjs.map +1 -0
  117. package/dist/chunk-W6RTHQGP.mjs +1 -0
  118. package/dist/chunk-W6RTHQGP.mjs.map +1 -0
  119. package/dist/chunk-ZELBCPDC.mjs +369 -0
  120. package/dist/chunk-ZELBCPDC.mjs.map +1 -0
  121. package/dist/index.d.mts +1103 -544
  122. package/dist/index.d.ts +1103 -544
  123. package/dist/index.js +7032 -6033
  124. package/dist/index.js.map +1 -1
  125. package/dist/index.mjs +568 -2226
  126. package/dist/index.mjs.map +1 -1
  127. package/dist/resource-monitor-UZUGPIAU.mjs +9 -0
  128. package/dist/resource-monitor-UZUGPIAU.mjs.map +1 -0
  129. package/dist/storage-location-manager-HFNB3PCS.mjs +7 -0
  130. package/dist/storage-location-manager-HFNB3PCS.mjs.map +1 -0
  131. package/package.json +123 -2
  132. package/dist/builtins/local-backup/index.d.mts +0 -42
  133. package/dist/builtins/local-backup/index.d.ts +0 -42
  134. package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.mts +0 -2
  135. package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.ts +0 -2
  136. package/dist/builtins/sqlite-storage/index.d.mts +0 -4
  137. package/dist/builtins/sqlite-storage/index.d.ts +0 -4
  138. package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.mts +0 -2
  139. package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +0 -2
  140. package/dist/builtins/winston-logging/index.d.mts +0 -30
  141. package/dist/builtins/winston-logging/index.d.ts +0 -30
  142. package/dist/chunk-2F3XZYRW.mjs.map +0 -1
  143. package/dist/chunk-LQFPAEQF.mjs +0 -147
  144. package/dist/chunk-LQFPAEQF.mjs.map +0 -1
  145. package/dist/chunk-R3DIIBBX.mjs +0 -532
  146. package/dist/chunk-R3DIIBBX.mjs.map +0 -1
  147. package/dist/chunk-SMNR44VG.mjs +0 -386
  148. package/dist/chunk-SMNR44VG.mjs.map +0 -1
  149. package/dist/chunk-SO4LROOT.mjs.map +0 -1
  150. package/dist/chunk-SPA4JBKN.mjs +0 -175
  151. package/dist/chunk-SPA4JBKN.mjs.map +0 -1
  152. package/dist/dist-3BY63UQ5.mjs +0 -2151
  153. package/dist/dist-3BY63UQ5.mjs.map +0 -1
  154. package/dist/filesystem-storage.addon-C42r589X.d.mts +0 -57
  155. package/dist/filesystem-storage.addon-C42r589X.d.ts +0 -57
  156. package/dist/sql-schema-CKz78rId.d.mts +0 -97
  157. package/dist/sql-schema-CKz78rId.d.ts +0 -97
  158. package/dist/sqlite-settings.addon-KwG-uKMP.d.mts +0 -79
  159. package/dist/sqlite-settings.addon-KwG-uKMP.d.ts +0 -79
  160. package/dist/storage-location-manager-KKDQNAKA.mjs +0 -7
  161. /package/dist/{storage-location-manager-KKDQNAKA.mjs.map → builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs.map} +0 -0
@@ -0,0 +1,297 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/builtins/hub-forwarder/index.ts
21
+ var hub_forwarder_exports = {};
22
+ __export(hub_forwarder_exports, {
23
+ HubForwarderAddon: () => HubForwarderAddon,
24
+ HubForwarderDestination: () => HubForwarderDestination,
25
+ default: () => HubForwarderAddon
26
+ });
27
+ module.exports = __toCommonJS(hub_forwarder_exports);
28
+
29
+ // src/builtins/hub-forwarder/hub-forwarder.addon.ts
30
+ var import_types = require("@camstack/types");
31
+
32
+ // src/logging/formatter.ts
33
+ var USE_COLOR = (() => {
34
+ try {
35
+ if (typeof process === "undefined") return false;
36
+ const env = process.env ?? {};
37
+ if (env["NO_COLOR"]) return false;
38
+ const force = env["FORCE_COLOR"];
39
+ if (force !== void 0) return force !== "" && force !== "0" && force !== "false";
40
+ return Boolean(process.stdout?.isTTY);
41
+ } catch {
42
+ return false;
43
+ }
44
+ })();
45
+ var NO_COLOR = (() => {
46
+ try {
47
+ return Boolean(process?.env?.["NO_COLOR"]);
48
+ } catch {
49
+ return false;
50
+ }
51
+ })();
52
+ var RESET = "\x1B[0m";
53
+ var ANSI = {
54
+ green: "\x1B[32m",
55
+ yellow: "\x1B[33m",
56
+ red: "\x1B[31m",
57
+ cyan: "\x1B[36m",
58
+ gray: "\x1B[90m"
59
+ };
60
+ var COLOR_BY_LEVEL = {
61
+ debug: ANSI.gray,
62
+ info: ANSI.green,
63
+ warn: ANSI.yellow,
64
+ error: ANSI.red
65
+ };
66
+ function paint(color, text, enabled) {
67
+ return enabled ? `${color}${text}${RESET}` : text;
68
+ }
69
+ function colorizeLevel(level, text, enabled) {
70
+ if (!enabled) return text;
71
+ const code = COLOR_BY_LEVEL[level];
72
+ return code ? `${code}${text}${RESET}` : text;
73
+ }
74
+ function padRight(value, width) {
75
+ if (value.length >= width) return value.slice(0, width);
76
+ return value + " ".repeat(width - value.length);
77
+ }
78
+ function resolveAgent(tags) {
79
+ const agentId = tags?.agentId;
80
+ if (typeof agentId === "string" && agentId.length > 0) return agentId;
81
+ const nodeId = tags?.nodeId;
82
+ if (typeof nodeId === "string" && nodeId.length > 0) {
83
+ return nodeId.includes("/") ? nodeId.split("/")[0] : nodeId;
84
+ }
85
+ return null;
86
+ }
87
+ function resolveAddon(entry) {
88
+ const addonId = entry.tags?.addonId;
89
+ if (typeof addonId === "string" && addonId.length > 0) return addonId;
90
+ return "system";
91
+ }
92
+ function resolveDevice(tags) {
93
+ const name = tags?.deviceName;
94
+ if (typeof name === "string" && name.length > 0) return name;
95
+ const id = tags?.deviceId;
96
+ if (typeof id === "number" && Number.isFinite(id)) return `#${id}`;
97
+ return null;
98
+ }
99
+ function buildBrand(entry) {
100
+ const agent = resolveAgent(entry.tags) ?? "?";
101
+ const addon = resolveAddon(entry);
102
+ return `${agent}/${addon}`;
103
+ }
104
+ function buildDeviceContext(entry) {
105
+ return resolveDevice(entry.tags);
106
+ }
107
+ function formatTimestamp(value) {
108
+ const date = value instanceof Date ? value : new Date(typeof value === "string" ? value : Date.now());
109
+ return date.toLocaleString("en-US", {
110
+ month: "numeric",
111
+ day: "numeric",
112
+ year: "numeric",
113
+ hour: "numeric",
114
+ minute: "2-digit",
115
+ second: "2-digit",
116
+ hour12: true
117
+ });
118
+ }
119
+ function formatMeta(meta) {
120
+ if (!meta) return "";
121
+ const keys = Object.keys(meta);
122
+ if (keys.length === 0) return "";
123
+ const parts = [];
124
+ for (const key of keys) {
125
+ const value = meta[key];
126
+ parts.push(`${key}=${formatMetaValue(value)}`);
127
+ }
128
+ return `{${parts.join(" ")}}`;
129
+ }
130
+ function formatMetaValue(value) {
131
+ if (value === null) return "null";
132
+ if (value === void 0) return "undefined";
133
+ if (typeof value === "string") {
134
+ return /\s|"/.test(value) ? JSON.stringify(value) : value;
135
+ }
136
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
137
+ if (value instanceof Error) return JSON.stringify(value.message);
138
+ try {
139
+ return JSON.stringify(value);
140
+ } catch {
141
+ return String(value);
142
+ }
143
+ }
144
+ var PID = typeof process !== "undefined" && typeof process.pid === "number" ? String(process.pid) : "?";
145
+ function formatLogLine(entry, options) {
146
+ const wantsColor = options?.colorize ?? USE_COLOR;
147
+ const colorize = wantsColor && !NO_COLOR;
148
+ const levelColor = COLOR_BY_LEVEL[entry.level];
149
+ const brand = paint(ANSI.green, `[${buildBrand(entry)}]`, colorize);
150
+ const entryPid = entry.tags?.pid;
151
+ const pid = typeof entryPid === "number" ? String(entryPid) : PID;
152
+ const timestamp = formatTimestamp(entry.timestamp);
153
+ const level = colorizeLevel(entry.level, padRight(entry.level.toUpperCase(), 5), colorize);
154
+ const device = buildDeviceContext(entry);
155
+ const ctxPart = device ? " " + paint(ANSI.yellow, `[${device}]`, colorize) : "";
156
+ const scope = typeof entry.scope === "string" && entry.scope.length > 0 ? entry.scope : null;
157
+ const scopePart = scope ? " " + paint(ANSI.cyan, `(${scope})`, colorize) : "";
158
+ const metaText = formatMeta(entry.meta);
159
+ const metaPart = metaText ? " " + paint(ANSI.gray, metaText, colorize) : "";
160
+ const message = colorize && levelColor ? `${levelColor}${entry.message}${RESET}` : entry.message;
161
+ return `${brand} ${pid} - ${timestamp} ${level}${ctxPart}${scopePart} ${message}${metaPart}`;
162
+ }
163
+
164
+ // src/builtins/hub-forwarder/hub-forwarder-destination.ts
165
+ var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
166
+ var HubForwarderDestination = class {
167
+ broker = null;
168
+ hubConnected = false;
169
+ outboundBuffer = [];
170
+ statusLogger = null;
171
+ async initialize() {
172
+ }
173
+ /**
174
+ * Provide a logger for the destination's own status messages
175
+ * (discovery, disconnect, reconnect). Routed through the agent's
176
+ * LogManager but never through this same destination — the owning
177
+ * addon must hand in a logger that does NOT route back here, or
178
+ * status writes will recurse.
179
+ */
180
+ setStatusLogger(logger) {
181
+ this.statusLogger = logger;
182
+ }
183
+ status(level, msg) {
184
+ if (this.statusLogger) {
185
+ if (level === "warn") this.statusLogger.warn(msg);
186
+ else this.statusLogger.info(msg);
187
+ return;
188
+ }
189
+ if (level === "warn") console.warn(`[hub-forwarder] ${msg}`);
190
+ else console.log(`[hub-forwarder] ${msg}`);
191
+ }
192
+ /**
193
+ * Attach the Moleculer broker so hub forwarding can start.
194
+ * Called by the owning addon from `onInitialize(ctx)` with
195
+ * `ctx.kernel.cluster?.broker`.
196
+ */
197
+ connectBroker(broker) {
198
+ this.broker = broker;
199
+ broker.waitForServices("log-receiver").then(() => {
200
+ this.hubConnected = true;
201
+ this.status("info", "log-receiver discovered \u2014 log forwarding active");
202
+ this.flushOutbound();
203
+ }).catch(() => {
204
+ });
205
+ broker.localBus.on("$node.disconnected", ({ node }) => {
206
+ if (node.id === "hub") {
207
+ this.hubConnected = false;
208
+ this.status("info", "Hub disconnected \u2014 log forwarding paused");
209
+ broker.waitForServices("log-receiver").then(() => {
210
+ this.hubConnected = true;
211
+ this.status("info", "Hub reconnected \u2014 log forwarding resumed");
212
+ this.flushOutbound();
213
+ }).catch(() => {
214
+ });
215
+ }
216
+ });
217
+ }
218
+ write(entry) {
219
+ if (this.hubConnected && this.broker) {
220
+ this.forward(entry);
221
+ return;
222
+ }
223
+ this.bufferOutbound(entry);
224
+ const line = formatLogLine(entry, { colorize: true });
225
+ if (entry.level === "error") console.error(line);
226
+ else if (entry.level === "warn") console.warn(line);
227
+ else console.log(line);
228
+ }
229
+ async query(_filter) {
230
+ return [];
231
+ }
232
+ async shutdown() {
233
+ this.hubConnected = false;
234
+ this.broker = null;
235
+ this.outboundBuffer.length = 0;
236
+ }
237
+ bufferOutbound(entry) {
238
+ this.outboundBuffer.push(entry);
239
+ if (this.outboundBuffer.length > DEFAULT_OUTBOUND_BUFFER_SIZE) {
240
+ this.outboundBuffer.splice(0, this.outboundBuffer.length - DEFAULT_OUTBOUND_BUFFER_SIZE);
241
+ }
242
+ }
243
+ flushOutbound() {
244
+ if (!this.broker || !this.hubConnected) return;
245
+ const pending = this.outboundBuffer.splice(0, this.outboundBuffer.length);
246
+ for (const entry of pending) {
247
+ this.forward(entry);
248
+ }
249
+ }
250
+ forward(entry) {
251
+ if (!this.broker) return;
252
+ this.broker.call("log-receiver.ingest", {
253
+ level: entry.level,
254
+ message: entry.message,
255
+ addonId: entry.tags?.addonId ?? "agent",
256
+ nodeId: entry.tags?.nodeId ?? this.broker.nodeID,
257
+ ...entry.scope !== void 0 ? { scope: entry.scope } : {},
258
+ ...entry.tags ? { tags: entry.tags } : {},
259
+ ...entry.meta ? { meta: entry.meta } : {}
260
+ }).catch(() => {
261
+ });
262
+ }
263
+ };
264
+
265
+ // src/builtins/hub-forwarder/hub-forwarder.addon.ts
266
+ var HubForwarderAddon = class extends import_types.BaseAddon {
267
+ destination = null;
268
+ constructor() {
269
+ super({});
270
+ }
271
+ async onInitialize() {
272
+ this.destination = new HubForwarderDestination();
273
+ await this.destination.initialize();
274
+ this.destination.setStatusLogger(this.ctx.logger);
275
+ const broker = this.ctx.kernel.cluster?.broker;
276
+ if (broker) {
277
+ this.destination.connectBroker(broker);
278
+ } else {
279
+ this.ctx.logger.warn("cluster.broker not available \u2014 hub forwarding disabled, console only");
280
+ }
281
+ this.ctx.logger.info("Hub forwarder log destination registered");
282
+ return [{ capability: import_types.logDestinationCapability, provider: this.destination }];
283
+ }
284
+ getDestination() {
285
+ return this.destination;
286
+ }
287
+ async onShutdown() {
288
+ await this.destination?.shutdown();
289
+ this.destination = null;
290
+ }
291
+ };
292
+ // Annotate the CommonJS export names for ESM import in node:
293
+ 0 && (module.exports = {
294
+ HubForwarderAddon,
295
+ HubForwarderDestination
296
+ });
297
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/builtins/hub-forwarder/index.ts","../../../src/builtins/hub-forwarder/hub-forwarder.addon.ts","../../../src/logging/formatter.ts","../../../src/builtins/hub-forwarder/hub-forwarder-destination.ts"],"sourcesContent":["export { HubForwarderAddon } from './hub-forwarder.addon.js'\nexport { HubForwarderAddon as default } from './hub-forwarder.addon.js'\nexport { HubForwarderDestination } from './hub-forwarder-destination.js'\n","import type { ProviderRegistration } from '@camstack/types'\nimport { BaseAddon, logDestinationCapability } from '@camstack/types'\nimport { HubForwarderDestination } from './hub-forwarder-destination.js'\n\n/**\n * Agent-only addon that provides the `log-destination` capability.\n * Writes all logs to the console and forwards to the hub via Moleculer when\n * reachable. The broker is read from `ctx.kernel.cluster?.broker`; outbound\n * log replay on hub-connect is handled internally by the destination.\n */\nexport class HubForwarderAddon extends BaseAddon {\n private destination: HubForwarderDestination | null = null\n\n constructor() { super({}) }\n\n protected async onInitialize(): Promise<ProviderRegistration[]> {\n this.destination = new HubForwarderDestination()\n await this.destination.initialize()\n // Status messages (discovery, disconnect) go through ctx.logger so they\n // appear in the structured log stream, not raw stdout.\n this.destination.setStatusLogger(this.ctx.logger)\n\n // Self-wire the broker when the kernel exposes one (agent + hub processes).\n // In-process unit tests may omit it — logs still go to the console.\n const broker = this.ctx.kernel.cluster?.broker\n if (broker) {\n this.destination.connectBroker(broker)\n } else {\n this.ctx.logger.warn('cluster.broker not available — hub forwarding disabled, console only')\n }\n\n this.ctx.logger.info('Hub forwarder log destination registered')\n return [{ capability: logDestinationCapability, provider: this.destination }]\n }\n\n getDestination(): HubForwarderDestination | null {\n return this.destination\n }\n\n protected async onShutdown(): Promise<void> {\n await this.destination?.shutdown()\n this.destination = null\n }\n}\n","/**\n * Canonical single-line formatter for every `LogEntry` that reaches a\n * console transport — hub-side `WinstonDestination` +\n * `ConsoleDestination`, agent-side `HubForwarderDestination`. One\n * definition so the three paths can't drift.\n *\n * Layout mirrors NestJS `ConsoleLogger` output:\n *\n * [Nest] 54994 - 04/20/2026, 12:45:53 AM LOG [InstanceLoader] TrpcModule dependencies initialized +0ms\n *\n * Mapping for camstack — cluster-aware:\n * - `[Nest]` (brand bracket) → `[<agent>/<addonId>]` so operators see\n * at a glance which node emitted the line\n * (matches the cluster topology)\n * - `54994` (pid) → `process.pid`\n * - `<timestamp>` → `M/D/YYYY, H:MM:SS AM`\n * - `LOG` / `WARN` / `ERROR` → `entry.level` upper-cased, colour per level\n * - `[InstanceLoader]` (ctx) → `[<device>]` — shown only when a device\n * tag is present; omitted otherwise\n * - `<message>` → `entry.message`\n * - trailing `+Nms` → we don't compute timing yet; omitted\n *\n * Rendered examples:\n * [hub/winston-logging] 71184 - 04/20/2026, 12:45:53 AM INFO Winston logging initialized\n * [hub/provider-rtsp] 71184 - 04/20/2026, 12:46:01 AM WARN [salone] probe failed {err=\"timeout\"}\n * [dev-agent-0/detection] 12345 - 04/20/2026, 12:47:15 AM ERROR [cortile] no detector {codec=av1}\n */\nimport type { LogEntry, LogTags } from '@camstack/types'\n\n// Emit ANSI colour codes when the runtime supports them. Heuristic\n// follows npm ecosystem convention so log-consumers can override:\n// - `NO_COLOR` env present → OFF (https://no-color.org/)\n// - `FORCE_COLOR=0` → OFF\n// - `FORCE_COLOR` truthy (1/2/3/true) → ON (forces even when piped)\n// - stdout.isTTY → ON\n// - else → OFF\n// Rationale: running via `concurrently` / `npm run dev` often pipes\n// stdout and strips `isTTY`, making colours disappear. Dev sets\n// `FORCE_COLOR=1` in the shell to opt back in; CI / file-piping\n// pipelines set `NO_COLOR=1` to strip.\n//\n// Destinations that always render for console (ConsoleDestination,\n// HubForwarderDestination) pass `colorize: true` explicitly — still\n// gated by NO_COLOR. File sinks (Winston JSON) pass `colorize: false`\n// so log files stay plain text regardless of the shell environment.\nconst USE_COLOR = (() => {\n try {\n if (typeof process === 'undefined') return false\n const env = process.env ?? {}\n if (env['NO_COLOR']) return false\n const force = env['FORCE_COLOR']\n if (force !== undefined) return force !== '' && force !== '0' && force !== 'false'\n return Boolean((process.stdout as { isTTY?: boolean })?.isTTY)\n } catch { return false }\n})()\n\n/** True when `NO_COLOR` is set — destinations that force colour on still honour this. */\nconst NO_COLOR = (() => {\n try { return Boolean(process?.env?.['NO_COLOR']) } catch { return false }\n})()\n\nconst RESET = '\\x1b[0m'\nconst ANSI = {\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n red: '\\x1b[31m',\n cyan: '\\x1b[36m',\n gray: '\\x1b[90m',\n} as const\n\nconst COLOR_BY_LEVEL: Readonly<Record<string, string>> = {\n debug: ANSI.gray,\n info: ANSI.green,\n warn: ANSI.yellow,\n error: ANSI.red,\n}\n\nfunction paint(color: string, text: string, enabled: boolean): string {\n return enabled ? `${color}${text}${RESET}` : text\n}\n\nfunction colorizeLevel(level: string, text: string, enabled: boolean): string {\n if (!enabled) return text\n const code = COLOR_BY_LEVEL[level]\n return code ? `${code}${text}${RESET}` : text\n}\n\n/** Right-pad `value` to exactly `width` characters. */\nfunction padRight(value: string, width: number): string {\n if (value.length >= width) return value.slice(0, width)\n return value + ' '.repeat(width - value.length)\n}\n\n/** Derive the agent — the top-level cluster node, never the forked-worker suffix. */\nfunction resolveAgent(tags: LogTags | undefined): string | null {\n const agentId = tags?.agentId\n if (typeof agentId === 'string' && agentId.length > 0) return agentId\n const nodeId = tags?.nodeId\n if (typeof nodeId === 'string' && nodeId.length > 0) {\n return nodeId.includes('/') ? nodeId.split('/')[0]! : nodeId\n }\n return null\n}\n\n/** Derive the addon — `tags.addonId` first; `system` when the tag is missing\n * (scope is no longer a fallback — it's a sub-component label, not identity). */\nfunction resolveAddon(entry: Pick<LogEntry, 'tags'>): string {\n const addonId = entry.tags?.addonId\n if (typeof addonId === 'string' && addonId.length > 0) return addonId\n return 'system'\n}\n\n/** Device name (or `#id` fallback) — used inside the context bracket when present. */\nfunction resolveDevice(tags: LogTags | undefined): string | null {\n const name = tags?.deviceName\n if (typeof name === 'string' && name.length > 0) return name\n const id = tags?.deviceId\n if (typeof id === 'number' && Number.isFinite(id)) return `#${id}`\n return null\n}\n\n/**\n * Build the brand bracket content — `<agent>/<addonId>`. Agent is\n * always shown (even `hub`) so operators never have to guess which\n * node emitted a line. Falls back to `?/<addon>` when tags don't\n * carry an agent id (pre-boot logs, test harnesses).\n */\nfunction buildBrand(entry: Pick<LogEntry, 'tags'>): string {\n const agent = resolveAgent(entry.tags) ?? '?'\n const addon = resolveAddon(entry)\n return `${agent}/${addon}`\n}\n\n/**\n * Build the optional device-context bracket. Returns `null` when the\n * line doesn't carry a device tag — renders as just the brand + message\n * without the second bracket. With a device tag: `salone` / `#42`.\n */\nfunction buildDeviceContext(entry: Pick<LogEntry, 'tags'>): string | null {\n return resolveDevice(entry.tags)\n}\n\n/**\n * NestJS-style locale timestamp: `M/D/YYYY, H:MM:SS AM`. Built with\n * `toLocaleString('en-US')` to match the default NestJS format that\n * operators are used to from Nest boot output.\n */\nfunction formatTimestamp(value: unknown): string {\n const date = value instanceof Date ? value : new Date(typeof value === 'string' ? value : Date.now())\n return date.toLocaleString('en-US', {\n month: 'numeric',\n day: 'numeric',\n year: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n second: '2-digit',\n hour12: true,\n })\n}\n\n/** Compact `{key=value key=\"with space\"}` rendering of an arbitrary object. Empty → ''. */\nfunction formatMeta(meta: Record<string, unknown> | undefined): string {\n if (!meta) return ''\n const keys = Object.keys(meta)\n if (keys.length === 0) return ''\n const parts: string[] = []\n for (const key of keys) {\n const value = meta[key]\n parts.push(`${key}=${formatMetaValue(value)}`)\n }\n return `{${parts.join(' ')}}`\n}\n\nfunction formatMetaValue(value: unknown): string {\n if (value === null) return 'null'\n if (value === undefined) return 'undefined'\n if (typeof value === 'string') {\n return /\\s|\"/.test(value) ? JSON.stringify(value) : value\n }\n if (typeof value === 'number' || typeof value === 'boolean') return String(value)\n if (value instanceof Error) return JSON.stringify(value.message)\n try { return JSON.stringify(value) } catch { return String(value) }\n}\n\n/** Cached renderer PID — fallback when the entry doesn't carry its own `tags.pid`. */\nconst PID = typeof process !== 'undefined' && typeof process.pid === 'number' ? String(process.pid) : '?'\n\n/** Options for `formatLogLine`. */\nexport interface FormatLogLineOptions {\n /**\n * Emit ANSI colour codes. When omitted, falls back to the shell-env\n * heuristic (`NO_COLOR`/`FORCE_COLOR`/`isTTY`). Destinations that\n * always target a console (ConsoleDestination, HubForwarderDestination)\n * pass `true`; file sinks (Winston JSON) pass `false` so logs on disk\n * stay plain text regardless of the shell env.\n *\n * `NO_COLOR=1` in the environment still wins — consumer opt-in beats\n * producer opt-in, matching the https://no-color.org/ convention.\n */\n readonly colorize?: boolean\n}\n\n/**\n * Render a `LogEntry` as one complete console line — no trailing newline.\n * Caller appends `\\n` (file sinks) or relies on `console.log` (stdout sink).\n *\n * PID column prefers `entry.tags.pid` when set (so forked-worker entries\n * carry the worker's OS pid even when the hub renders them), falling back\n * to the renderer's own `process.pid`.\n *\n * Colours (when enabled) follow the NestJS convention: the level token\n * AND the message body share the level colour (green/yellow/red/gray for\n * info/warn/error/debug). Brand, device context, scope and meta keep\n * their fixed hues so the structural fields stay visually distinct from\n * the message content.\n */\nexport function formatLogLine(entry: LogEntry, options?: FormatLogLineOptions): string {\n const wantsColor = options?.colorize ?? USE_COLOR\n const colorize = wantsColor && !NO_COLOR\n const levelColor = COLOR_BY_LEVEL[entry.level]\n\n const brand = paint(ANSI.green, `[${buildBrand(entry)}]`, colorize)\n const entryPid = entry.tags?.pid\n const pid = typeof entryPid === 'number' ? String(entryPid) : PID\n const timestamp = formatTimestamp(entry.timestamp)\n // Right-pad level to 5 chars (matches NestJS) so the context/message\n // column aligns across different levels without fixed-width hacks\n // on the surrounding fields.\n const level = colorizeLevel(entry.level, padRight(entry.level.toUpperCase(), 5), colorize)\n const device = buildDeviceContext(entry)\n const ctxPart = device ? ' ' + paint(ANSI.yellow, `[${device}]`, colorize) : ''\n const scope = typeof entry.scope === 'string' && entry.scope.length > 0 ? entry.scope : null\n const scopePart = scope ? ' ' + paint(ANSI.cyan, `(${scope})`, colorize) : ''\n const metaText = formatMeta(entry.meta)\n const metaPart = metaText ? ' ' + paint(ANSI.gray, metaText, colorize) : ''\n // NestJS layout: `[<agent>/<addon>] <pid> - <timestamp> <LEVEL> [<device>] (<scope>) <message>`\n // Message body is tinted by level colour so `error`/`warn` stand out at a glance.\n const message = colorize && levelColor\n ? `${levelColor}${entry.message}${RESET}`\n : entry.message\n return `${brand} ${pid} - ${timestamp} ${level}${ctxPart}${scopePart} ${message}${metaPart}`\n}\n","import type { IClusterBroker, ILogDestination, IScopedLogger, LogEntry, LogFilter } from '@camstack/types'\nimport { formatLogLine } from '../../logging/formatter.js'\n\nconst DEFAULT_OUTBOUND_BUFFER_SIZE = 500\n\n/**\n * Log destination for agent mode.\n *\n * - Writes to console ONLY when hub is not yet reachable (cold-start\n * fallback). Forked-worker agents share stdout with their parent\n * hub, so logging to local console AND forwarding to hub's\n * `log-receiver` would print the entry twice on the hub terminal.\n * Once the hub is discovered, local console output stops and the\n * hub's own ConsoleDestination owns the render.\n * - When a Moleculer broker is connected and the hub node is reachable,\n * forwards every log entry to the hub via `log-receiver.ingest`.\n * - Entries written before the hub is reachable are buffered internally\n * (ring-buffered to `DEFAULT_OUTBOUND_BUFFER_SIZE`) and flushed on connect,\n * so boot-time logs still reach the hub without any external replay trigger.\n */\nexport class HubForwarderDestination implements ILogDestination {\n private broker: IClusterBroker | null = null\n private hubConnected = false\n private readonly outboundBuffer: LogEntry[] = []\n private statusLogger: IScopedLogger | null = null\n\n async initialize(): Promise<void> {\n // Console destination is always active — no setup needed.\n }\n\n /**\n * Provide a logger for the destination's own status messages\n * (discovery, disconnect, reconnect). Routed through the agent's\n * LogManager but never through this same destination — the owning\n * addon must hand in a logger that does NOT route back here, or\n * status writes will recurse.\n */\n setStatusLogger(logger: IScopedLogger): void {\n this.statusLogger = logger\n }\n\n private status(level: 'info' | 'warn', msg: string): void {\n if (this.statusLogger) {\n if (level === 'warn') this.statusLogger.warn(msg)\n else this.statusLogger.info(msg)\n return\n }\n // Cold-start fallback: status logger not yet wired.\n if (level === 'warn') console.warn(`[hub-forwarder] ${msg}`)\n else console.log(`[hub-forwarder] ${msg}`)\n }\n\n /**\n * Attach the Moleculer broker so hub forwarding can start.\n * Called by the owning addon from `onInitialize(ctx)` with\n * `ctx.kernel.cluster?.broker`.\n */\n connectBroker(broker: IClusterBroker): void {\n this.broker = broker\n\n // Wait for `log-receiver` service (no timeout — waits until available).\n // The service is registered on the hub after app.init(), so it may\n // appear after node discovery. This is fully event-driven.\n broker.waitForServices('log-receiver')\n .then(() => {\n this.hubConnected = true\n this.status('info', 'log-receiver discovered — log forwarding active')\n this.flushOutbound()\n })\n .catch(() => { /* broker stopped before discovery */ })\n\n broker.localBus.on('$node.disconnected', ({ node }) => {\n if (node.id === 'hub') {\n this.hubConnected = false\n this.status('info', 'Hub disconnected — log forwarding paused')\n // Re-wait for reconnect\n broker.waitForServices('log-receiver')\n .then(() => {\n this.hubConnected = true\n this.status('info', 'Hub reconnected — log forwarding resumed')\n this.flushOutbound()\n })\n .catch(() => { /* broker stopped */ })\n }\n })\n }\n\n write(entry: LogEntry): void {\n // 1. Forward to hub when connected, otherwise buffer for flush-on-connect.\n if (this.hubConnected && this.broker) {\n this.forward(entry)\n return\n }\n this.bufferOutbound(entry)\n\n // 2. Local console output ONLY as a cold-start fallback. Forked-worker\n // stdout is already piped to the hub's terminal; once the hub\n // ingests our forwarded entry it renders it there. Printing\n // locally would show the same line twice.\n const line = formatLogLine(entry, { colorize: true })\n if (entry.level === 'error') console.error(line)\n else if (entry.level === 'warn') console.warn(line)\n else console.log(line)\n }\n\n async query(_filter: LogFilter): Promise<readonly LogEntry[]> {\n // Agent does not support log queries — hub holds the queryable store.\n return []\n }\n\n async shutdown(): Promise<void> {\n this.hubConnected = false\n this.broker = null\n this.outboundBuffer.length = 0\n }\n\n private bufferOutbound(entry: LogEntry): void {\n this.outboundBuffer.push(entry)\n // Ring-buffer: drop oldest entries once we're past the cap so the\n // outbound buffer never grows without bound.\n if (this.outboundBuffer.length > DEFAULT_OUTBOUND_BUFFER_SIZE) {\n this.outboundBuffer.splice(0, this.outboundBuffer.length - DEFAULT_OUTBOUND_BUFFER_SIZE)\n }\n }\n\n private flushOutbound(): void {\n if (!this.broker || !this.hubConnected) return\n const pending = this.outboundBuffer.splice(0, this.outboundBuffer.length)\n for (const entry of pending) {\n this.forward(entry)\n }\n }\n\n private forward(entry: LogEntry): void {\n if (!this.broker) return\n this.broker.call('log-receiver.ingest', {\n level: entry.level,\n message: entry.message,\n addonId: entry.tags?.addonId ?? 'agent',\n nodeId: entry.tags?.nodeId ?? this.broker.nodeID,\n ...(entry.scope !== undefined ? { scope: entry.scope } : {}),\n ...(entry.tags ? { tags: entry.tags } : {}),\n ...(entry.meta ? { meta: entry.meta } : {}),\n }).catch(() => {\n // Hub unreachable — silently drop. Will resume on reconnect.\n })\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,11 @@
1
+ import {
2
+ HubForwarderAddon,
3
+ HubForwarderDestination
4
+ } from "../../chunk-QX4RH25I.mjs";
5
+ import "../../chunk-2F76X6NL.mjs";
6
+ export {
7
+ HubForwarderAddon,
8
+ HubForwarderDestination,
9
+ HubForwarderAddon as default
10
+ };
11
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}