@camstack/system 1.0.2

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 (262) hide show
  1. package/dist/addon/addon-api-factory.d.ts +35 -0
  2. package/dist/addon-routes/addon-route-registry.d.ts +37 -0
  3. package/dist/addon-runner.js +599 -0
  4. package/dist/addon-runner.mjs +597 -0
  5. package/dist/auth/api-key-manager.d.ts +26 -0
  6. package/dist/auth/auth-manager.d.ts +109 -0
  7. package/dist/auth/parse-record.d.ts +18 -0
  8. package/dist/auth/scope-matcher.d.ts +7 -0
  9. package/dist/auth/scoped-token-manager.d.ts +40 -0
  10. package/dist/auth/totp-manager.d.ts +51 -0
  11. package/dist/auth/user-manager.d.ts +34 -0
  12. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.d.ts +53 -0
  13. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +259 -0
  14. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +251 -0
  15. package/dist/builtins/addon-pages-aggregator/dedupe-pages.d.ts +6 -0
  16. package/dist/builtins/addon-pages-aggregator/index.d.ts +1 -0
  17. package/dist/builtins/addon-pages-aggregator/index.js +8 -0
  18. package/dist/builtins/addon-pages-aggregator/index.mjs +2 -0
  19. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.d.ts +47 -0
  20. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +228 -0
  21. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +220 -0
  22. package/dist/builtins/addon-widgets-aggregator/index.d.ts +1 -0
  23. package/dist/builtins/addon-widgets-aggregator/index.js +8 -0
  24. package/dist/builtins/addon-widgets-aggregator/index.mjs +2 -0
  25. package/dist/builtins/alerts/alerts.addon.d.ts +81 -0
  26. package/dist/builtins/alerts/alerts.addon.js +601 -0
  27. package/dist/builtins/alerts/alerts.addon.mjs +595 -0
  28. package/dist/builtins/alerts/index.d.ts +1 -0
  29. package/dist/builtins/alerts/index.js +4 -0
  30. package/dist/builtins/alerts/index.mjs +2 -0
  31. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +147 -0
  32. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2229 -0
  33. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2220 -0
  34. package/dist/builtins/backup-orchestrator/cron-helpers.d.ts +23 -0
  35. package/dist/builtins/backup-orchestrator/destination-policy.d.ts +72 -0
  36. package/dist/builtins/backup-orchestrator/download-helpers.d.ts +12 -0
  37. package/dist/builtins/backup-orchestrator/index.d.ts +2 -0
  38. package/dist/builtins/backup-orchestrator/index.js +8 -0
  39. package/dist/builtins/backup-orchestrator/index.mjs +2 -0
  40. package/dist/builtins/backup-orchestrator/manifest-store.d.ts +77 -0
  41. package/dist/builtins/console-logging/console-destination.d.ts +13 -0
  42. package/dist/builtins/console-logging/console-logging.addon.d.ts +25 -0
  43. package/dist/builtins/console-logging/index.d.ts +3 -0
  44. package/dist/builtins/console-logging/index.js +104 -0
  45. package/dist/builtins/console-logging/index.mjs +95 -0
  46. package/dist/builtins/device-manager/device-config-contribution.d.ts +32 -0
  47. package/dist/builtins/device-manager/device-event-propagator.d.ts +26 -0
  48. package/dist/builtins/device-manager/device-link-overlay.d.ts +23 -0
  49. package/dist/builtins/device-manager/device-link-resolver.d.ts +15 -0
  50. package/dist/builtins/device-manager/device-manager.addon.d.ts +452 -0
  51. package/dist/builtins/device-manager/device-manager.addon.js +3299 -0
  52. package/dist/builtins/device-manager/device-manager.addon.mjs +3292 -0
  53. package/dist/builtins/device-manager/index.d.ts +2 -0
  54. package/dist/builtins/device-manager/index.js +8 -0
  55. package/dist/builtins/device-manager/index.mjs +2 -0
  56. package/dist/builtins/hub-forwarder/hub-forwarder-destination.d.ts +44 -0
  57. package/dist/builtins/hub-forwarder/hub-forwarder.addon.d.ts +15 -0
  58. package/dist/builtins/hub-forwarder/index.d.ts +3 -0
  59. package/dist/builtins/hub-forwarder/index.js +154 -0
  60. package/dist/builtins/hub-forwarder/index.mjs +145 -0
  61. package/dist/builtins/local-auth/auth-schema.d.ts +26 -0
  62. package/dist/builtins/local-auth/index.d.ts +1 -0
  63. package/dist/builtins/local-auth/index.js +4 -0
  64. package/dist/builtins/local-auth/index.mjs +2 -0
  65. package/dist/builtins/local-auth/local-auth.addon.d.ts +18 -0
  66. package/dist/builtins/local-auth/local-auth.addon.js +8094 -0
  67. package/dist/builtins/local-auth/local-auth.addon.mjs +8063 -0
  68. package/dist/builtins/local-auth/oauth-grants.d.ts +45 -0
  69. package/dist/builtins/local-auth/oauth-session-manager.d.ts +50 -0
  70. package/dist/builtins/local-network/index.d.ts +2 -0
  71. package/dist/builtins/local-network/index.js +10 -0
  72. package/dist/builtins/local-network/index.mjs +2 -0
  73. package/dist/builtins/local-network/local-network.addon.d.ts +150 -0
  74. package/dist/builtins/local-network/local-network.addon.js +489 -0
  75. package/dist/builtins/local-network/local-network.addon.mjs +477 -0
  76. package/dist/builtins/native-metrics/index.d.ts +2 -0
  77. package/dist/builtins/native-metrics/native-metrics-provider.d.ts +48 -0
  78. package/dist/builtins/native-metrics/native-metrics.addon.d.ts +73 -0
  79. package/dist/builtins/native-metrics/native-metrics.addon.js +922 -0
  80. package/dist/builtins/native-metrics/native-metrics.addon.mjs +914 -0
  81. package/dist/builtins/platform-probe/hardware-decode-accel-probe.d.ts +37 -0
  82. package/dist/builtins/platform-probe/hardware-encoder-probe.d.ts +13 -0
  83. package/dist/builtins/platform-probe/index.d.ts +22 -0
  84. package/dist/builtins/platform-probe/index.js +834 -0
  85. package/dist/builtins/platform-probe/index.mjs +822 -0
  86. package/dist/builtins/platform-probe/inference-config-resolver.d.ts +29 -0
  87. package/dist/builtins/platform-probe/intel-accelerators.d.ts +11 -0
  88. package/dist/builtins/platform-probe/platform-scorer.d.ts +30 -0
  89. package/dist/builtins/platform-probe/runtime-packages.d.ts +6 -0
  90. package/dist/builtins/remote-access-orchestrator/enabled-providers-reconcile.d.ts +96 -0
  91. package/dist/builtins/remote-access-orchestrator/index.d.ts +1 -0
  92. package/dist/builtins/remote-access-orchestrator/index.js +8 -0
  93. package/dist/builtins/remote-access-orchestrator/index.mjs +2 -0
  94. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.d.ts +40 -0
  95. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +214 -0
  96. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +208 -0
  97. package/dist/builtins/shared/settle-sources.d.ts +22 -0
  98. package/dist/builtins/snapshot/index.d.ts +2 -0
  99. package/dist/builtins/snapshot/index.js +494 -0
  100. package/dist/builtins/snapshot/index.mjs +488 -0
  101. package/dist/builtins/snapshot/snapshot.addon.d.ts +120 -0
  102. package/dist/builtins/sqlite-storage/config-store.d.ts +8 -0
  103. package/dist/builtins/sqlite-storage/device-store.d.ts +23 -0
  104. package/dist/builtins/sqlite-storage/filesystem-browse-provider.d.ts +25 -0
  105. package/dist/builtins/sqlite-storage/filesystem-storage-provider.d.ts +83 -0
  106. package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.ts +32 -0
  107. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +396 -0
  108. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +388 -0
  109. package/dist/builtins/sqlite-storage/index.d.ts +8 -0
  110. package/dist/builtins/sqlite-storage/index.js +62 -0
  111. package/dist/builtins/sqlite-storage/index.mjs +49 -0
  112. package/dist/builtins/sqlite-storage/integration-registry.d.ts +27 -0
  113. package/dist/builtins/sqlite-storage/path-guard.d.ts +4 -0
  114. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +102 -0
  115. package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +14 -0
  116. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +644 -0
  117. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +636 -0
  118. package/dist/builtins/storage-orchestrator/index.d.ts +6 -0
  119. package/dist/builtins/storage-orchestrator/index.js +10 -0
  120. package/dist/builtins/storage-orchestrator/index.mjs +2 -0
  121. package/dist/builtins/storage-orchestrator/location-store.d.ts +49 -0
  122. package/dist/builtins/storage-orchestrator/provider-discovery.d.ts +10 -0
  123. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +103 -0
  124. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1138 -0
  125. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1128 -0
  126. package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts +236 -0
  127. package/dist/builtins/storage-orchestrator/storage-pressure-manager.d.ts +38 -0
  128. package/dist/builtins/system-backup/system-backup.service.d.ts +137 -0
  129. package/dist/builtins/system-config/index.d.ts +1 -0
  130. package/dist/builtins/system-config/index.js +8 -0
  131. package/dist/builtins/system-config/index.mjs +2 -0
  132. package/dist/builtins/system-config/system-config.addon.d.ts +10 -0
  133. package/dist/builtins/system-config/system-config.addon.js +232 -0
  134. package/dist/builtins/system-config/system-config.addon.mjs +226 -0
  135. package/dist/builtins/winston-logging/index.d.ts +3 -0
  136. package/dist/builtins/winston-logging/index.js +156 -0
  137. package/dist/builtins/winston-logging/index.mjs +144 -0
  138. package/dist/builtins/winston-logging/winston-destination.d.ts +21 -0
  139. package/dist/builtins/winston-logging/winston-logging.addon.d.ts +19 -0
  140. package/dist/chunk-CNf5ZN-e.mjs +37 -0
  141. package/dist/chunk-Cek0wNdY.js +64 -0
  142. package/dist/download/model-download-service.d.ts +41 -0
  143. package/dist/download/model-downloader.d.ts +31 -0
  144. package/dist/events/event-bus.d.ts +10 -0
  145. package/dist/events/system-event-bus.d.ts +14 -0
  146. package/dist/feature/feature-manager.d.ts +11 -0
  147. package/dist/formatter-B7qW8bPJ.mjs +162 -0
  148. package/dist/formatter-DqAKDlvN.js +167 -0
  149. package/dist/http/authenticated-file-server.d.ts +53 -0
  150. package/dist/http/data-plane-registry.d.ts +23 -0
  151. package/dist/http/file-data-plane.d.ts +10 -0
  152. package/dist/http/reverse-proxy.d.ts +15 -0
  153. package/dist/index.d.ts +82 -0
  154. package/dist/index.js +93485 -0
  155. package/dist/index.mjs +93179 -0
  156. package/dist/intel-accelerators-Gg0P5mnl.js +20 -0
  157. package/dist/intel-accelerators-hGgpZ0pX.mjs +19 -0
  158. package/dist/kernel/addon-class-resolver.d.ts +4 -0
  159. package/dist/kernel/addon-engine-manager.d.ts +22 -0
  160. package/dist/kernel/addon-health-monitor.d.ts +154 -0
  161. package/dist/kernel/addon-installer.d.ts +208 -0
  162. package/dist/kernel/addon-loader.d.ts +106 -0
  163. package/dist/kernel/addon-manifest.d.ts +77 -0
  164. package/dist/kernel/capability-handle.d.ts +46 -0
  165. package/dist/kernel/capability-registry.d.ts +412 -0
  166. package/dist/kernel/config-manager.d.ts +212 -0
  167. package/dist/kernel/config-schema.d.ts +93 -0
  168. package/dist/kernel/custom-action-registry.d.ts +23 -0
  169. package/dist/kernel/deps/addon-deps-manager.d.ts +19 -0
  170. package/dist/kernel/deps/manifest-native-deps.d.ts +25 -0
  171. package/dist/kernel/deps/manifest-python-deps.d.ts +20 -0
  172. package/dist/kernel/device-registry.d.ts +29 -0
  173. package/dist/kernel/fs-utils.d.ts +41 -0
  174. package/dist/kernel/hwaccel/hwaccel-resolver.d.ts +19 -0
  175. package/dist/kernel/hwaccel/hwaccel-service.d.ts +4 -0
  176. package/dist/kernel/index.d.ts +74 -0
  177. package/dist/kernel/infra-capabilities.d.ts +13 -0
  178. package/dist/kernel/moleculer/addon-context-factory.d.ts +91 -0
  179. package/dist/kernel/moleculer/addon-data-plane-facility.d.ts +19 -0
  180. package/dist/kernel/moleculer/addon-runner.d.ts +1 -0
  181. package/dist/kernel/moleculer/addon-service-factory.d.ts +50 -0
  182. package/dist/kernel/moleculer/broker-factory.d.ts +50 -0
  183. package/dist/kernel/moleculer/cap-usage-registry.d.ts +46 -0
  184. package/dist/kernel/moleculer/capabilities-access.d.ts +21 -0
  185. package/dist/kernel/moleculer/child-addon-call-dispatch.d.ts +46 -0
  186. package/dist/kernel/moleculer/child-cap-dispatch.d.ts +20 -0
  187. package/dist/kernel/moleculer/cluster-secret.d.ts +15 -0
  188. package/dist/kernel/moleculer/core-cap-service.d.ts +50 -0
  189. package/dist/kernel/moleculer/crash-supervisor.d.ts +50 -0
  190. package/dist/kernel/moleculer/device-cap-proxy.d.ts +79 -0
  191. package/dist/kernel/moleculer/event-bus-core.d.ts +53 -0
  192. package/dist/kernel/moleculer/event-bus.d.ts +53 -0
  193. package/dist/kernel/moleculer/hub-log-forwarder.d.ts +36 -0
  194. package/dist/kernel/moleculer/hub-service.d.ts +35 -0
  195. package/dist/kernel/moleculer/node-registry.d.ts +126 -0
  196. package/dist/kernel/moleculer/process-context.d.ts +4 -0
  197. package/dist/kernel/moleculer/process-service.d.ts +72 -0
  198. package/dist/kernel/moleculer/provider-registry.d.ts +28 -0
  199. package/dist/kernel/moleculer/readiness-context.d.ts +62 -0
  200. package/dist/kernel/moleculer/readiness-service.d.ts +7 -0
  201. package/dist/kernel/moleculer/register-node-client.d.ts +35 -0
  202. package/dist/kernel/moleculer/remote-logger.d.ts +43 -0
  203. package/dist/kernel/moleculer/resilient-cap-call.d.ts +28 -0
  204. package/dist/kernel/moleculer/stream-probe-service.d.ts +9 -0
  205. package/dist/kernel/moleculer/trpc-links.d.ts +189 -0
  206. package/dist/kernel/moleculer/typed-array-serde.d.ts +25 -0
  207. package/dist/kernel/moleculer/worker-device-restore.d.ts +10 -0
  208. package/dist/kernel/provider-kind-drift.d.ts +12 -0
  209. package/dist/kernel/restart-coordinator.d.ts +90 -0
  210. package/dist/kernel/storage-location-registry.d.ts +40 -0
  211. package/dist/kernel/transport/cap-action-name.d.ts +100 -0
  212. package/dist/kernel/transport/cap-route-resolver.d.ts +148 -0
  213. package/dist/kernel/transport/cap-route.d.ts +148 -0
  214. package/dist/kernel/transport/child-cap-protocol.d.ts +136 -0
  215. package/dist/kernel/transport/create-local-transport.d.ts +7 -0
  216. package/dist/kernel/transport/frame-codec.d.ts +7 -0
  217. package/dist/kernel/transport/index.d.ts +27 -0
  218. package/dist/kernel/transport/local-child-client.d.ts +136 -0
  219. package/dist/kernel/transport/local-child-registry.d.ts +179 -0
  220. package/dist/kernel/transport/local-endpoint-path.d.ts +6 -0
  221. package/dist/kernel/transport/local-transport.d.ts +46 -0
  222. package/dist/kernel/transport/parent-unowned-call.d.ts +75 -0
  223. package/dist/kernel/transport/socket-channel.d.ts +27 -0
  224. package/dist/kernel/transport/uds-event-bridge.d.ts +36 -0
  225. package/dist/kernel/transport/uds-event-bus.d.ts +22 -0
  226. package/dist/kernel/transport/uds-local-transport.d.ts +18 -0
  227. package/dist/kernel/transport/uds-log-ingest.d.ts +28 -0
  228. package/dist/kernel/transport/uds-logger.d.ts +44 -0
  229. package/dist/kernel/utils/ring-buffer.d.ts +15 -0
  230. package/dist/kernel/workspace-detect.d.ts +9 -0
  231. package/dist/lifecycle/lifecycle-state-machine.d.ts +28 -0
  232. package/dist/logging/formatter.d.ts +30 -0
  233. package/dist/logging/log-manager.d.ts +54 -0
  234. package/dist/logging/log-ring-buffer.d.ts +47 -0
  235. package/dist/logging/partitioned-log-buffer.d.ts +35 -0
  236. package/dist/logging/scoped-logger.d.ts +17 -0
  237. package/dist/main-DNnMW7Z2.js +9983 -0
  238. package/dist/main-rtjOwPBR.mjs +9976 -0
  239. package/dist/manifest-python-deps-D1DbAQEv.js +6724 -0
  240. package/dist/manifest-python-deps-DZsKTbs1.mjs +6315 -0
  241. package/dist/network/network-quality.d.ts +11 -0
  242. package/dist/notification/notification-service.d.ts +37 -0
  243. package/dist/notification/toast-service.d.ts +22 -0
  244. package/dist/pipeline/engine-manager-resolver.d.ts +15 -0
  245. package/dist/pipeline/pipeline-runner.d.ts +8 -0
  246. package/dist/pipeline/pipeline-validator.d.ts +13 -0
  247. package/dist/process/resource-monitor.d.ts +11 -0
  248. package/dist/python/python-env-manager.d.ts +12 -0
  249. package/dist/repl/interfaces.d.ts +31 -0
  250. package/dist/repl/repl-engine.d.ts +8 -0
  251. package/dist/resource-monitor-ClDGFyf6.mjs +57 -0
  252. package/dist/resource-monitor-IIEanuJt.js +74 -0
  253. package/dist/settle-sources-Bhsy57y-.js +38 -0
  254. package/dist/settle-sources-CDtNC8ub.mjs +33 -0
  255. package/dist/storage/fs-storage-backend.d.ts +40 -0
  256. package/dist/storage/storage-location-manager.d.ts +23 -0
  257. package/dist/storage/storage-manager.d.ts +83 -0
  258. package/dist/tar-BgAEMRBR.js +5434 -0
  259. package/dist/tar-ByMOPNM0.mjs +5429 -0
  260. package/dist/tls/cert-manager.d.ts +26 -0
  261. package/dist/tls/index.d.ts +1 -0
  262. package/package.json +343 -0
@@ -0,0 +1,251 @@
1
+ import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
2
+ import * as fs from "node:fs";
3
+ import * as path$1 from "node:path";
4
+ import { BaseAddon, EventCategory, addonPagesCapability, errMsg } from "@camstack/types";
5
+ import { randomUUID } from "node:crypto";
6
+ //#region src/builtins/addon-pages-aggregator/dedupe-pages.ts
7
+ /** Stable identity for an addon page, independent of which node reported it. */
8
+ function pageKey(info) {
9
+ return `${info.addonId}::${info.page.id}`;
10
+ }
11
+ /**
12
+ * Return a new list with duplicate `(addonId, page.id)` entries removed,
13
+ * preserving first-seen order. Pure — never mutates the input.
14
+ */
15
+ function dedupePages(pages) {
16
+ const seen = /* @__PURE__ */ new Set();
17
+ const out = [];
18
+ for (const info of pages) {
19
+ const key = pageKey(info);
20
+ if (seen.has(key)) continue;
21
+ seen.add(key);
22
+ out.push(info);
23
+ }
24
+ return out;
25
+ }
26
+ //#endregion
27
+ //#region src/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.ts
28
+ /**
29
+ * Addon Pages Aggregator — hub-local builtin that owns the singleton
30
+ * `addon-pages` cap.
31
+ *
32
+ * Walks every registered `addon-pages-source` (collection) provider and
33
+ * emits an enriched `AddonPageInfo[]` list with versioned `bundleUrl`s
34
+ * pointing at `/api/addon-pages/<addonId>/<bundle>?v=<mtime>`. The
35
+ * filesystem `mtime` cache-buster lets the browser pick up addon
36
+ * rebuilds without manual reload — same scheme the original
37
+ * hand-written `AddonPagesService.listPages` used before this split.
38
+ *
39
+ * The static file endpoint (`/api/addon-pages/:addonId/*`) is still
40
+ * served by `AddonPagesService.resolveBundle()` on the server side; this
41
+ * addon only owns the listing surface.
42
+ *
43
+ * Why a builtin rather than a cap-providers helper:
44
+ * - The aggregator is conceptually the "addon-pages provider" — addons
45
+ * own caps, not the server. Living in `@camstack/system/builtins` keeps
46
+ * the surface symmetrical with `system-config`, `local-auth`, etc.
47
+ * - Lets the aggregator subscribe to source readiness without piping a
48
+ * CapabilityRegistry handle through `RouterServices`.
49
+ */
50
+ /**
51
+ * Backoff schedule (ms) used to retry sources that failed during a
52
+ * `listPages()` round-trip — typically because the cap was just
53
+ * registered (provider connected via Moleculer) but the worker-side
54
+ * action registration hadn't propagated yet, so `Service '...listPages'
55
+ * is not found on '<node>'` raced ahead of the call.
56
+ *
57
+ * We schedule one retry per entry; if every retry fails we stop
58
+ * (the next aggregate() run will pick the source up again). On
59
+ * success we re-emit `AddonPageReady` so admin-ui invalidates its
60
+ * `addonPages.listPages` query and the sidebar populates without a
61
+ * page reload.
62
+ */
63
+ var RETRY_BACKOFF_MS = [
64
+ 500,
65
+ 1500,
66
+ 4e3
67
+ ];
68
+ /**
69
+ * Per-source ceiling for a single `listPages()` round-trip. A healthy
70
+ * source answers in well under this (hub-local UDS <100ms, a reachable
71
+ * remote agent <1s). A source that's unreachable — e.g. an agent-hosted
72
+ * addon whose cap routes through a Moleculer `waitForServices` that waits
73
+ * its full 30s discovery timeout for a node that will never appear — must
74
+ * NOT block the whole listing: we time it out fast, serve its cached
75
+ * snapshot, and let the background retry recover it. Combined with the
76
+ * parallel fan-out below, one slow/dead source can no longer stall the
77
+ * sidebar query (which otherwise hangs long enough to trip the WS
78
+ * keepalive → "server unreachable").
79
+ */
80
+ var PER_SOURCE_TIMEOUT_MS = 2500;
81
+ var AddonPagesAggregatorAddon = class extends BaseAddon {
82
+ id = "addon-pages-aggregator";
83
+ resolvedPaths = null;
84
+ /**
85
+ * Last successful `listPages()` snapshot per source. Used as the
86
+ * "stale-but-valid" fallback when a source transiently fails — drops
87
+ * happen often enough during boot (Moleculer service-discovery
88
+ * window) that swallowing the error and returning empty leaves the
89
+ * sidebar with nothing for several seconds. Keeping the previous
90
+ * good entry means a flake is invisible to the operator.
91
+ */
92
+ lastGood = /* @__PURE__ */ new Map();
93
+ /** In-flight retry guards keyed by sourceId. Avoids double-scheduling. */
94
+ retryTimers = /* @__PURE__ */ new Map();
95
+ constructor() {
96
+ super({});
97
+ }
98
+ async onInitialize() {
99
+ this.resolvedPaths = await this.resolvePaths();
100
+ const provider = { listPages: async () => this.aggregate() };
101
+ this.ctx.logger.info("Initialized — aggregating addon-pages-source providers");
102
+ return [{
103
+ capability: addonPagesCapability,
104
+ provider
105
+ }];
106
+ }
107
+ async onShutdown() {
108
+ for (const t of this.retryTimers.values()) clearTimeout(t);
109
+ this.retryTimers.clear();
110
+ this.lastGood.clear();
111
+ }
112
+ async aggregate() {
113
+ const sources = this.capabilities?.getCollection("addon-pages-source") ?? [];
114
+ const out = [];
115
+ const seenIds = /* @__PURE__ */ new Set();
116
+ const settled = await settleSourcesWithTimeout(sources.map((source) => [source.id, () => Promise.resolve(source.listPages())]), PER_SOURCE_TIMEOUT_MS);
117
+ for (const [sourceId, result] of settled) {
118
+ seenIds.add(sourceId);
119
+ if (result.ok) {
120
+ const enriched = result.value.map((page) => ({
121
+ addonId: sourceId,
122
+ page,
123
+ bundleUrl: this.makeBundleUrl(sourceId, page.bundle)
124
+ }));
125
+ for (const item of enriched) out.push(item);
126
+ this.lastGood.set(sourceId, enriched);
127
+ } else {
128
+ this.ctx.logger.warn("addon-pages-source provider failed", { meta: {
129
+ sourceId,
130
+ error: result.error.message
131
+ } });
132
+ const cached = this.lastGood.get(sourceId);
133
+ if (cached !== void 0) {
134
+ for (const item of cached) out.push(item);
135
+ this.ctx.logger.info("addon-pages-source falling back to cached snapshot", { meta: {
136
+ sourceId,
137
+ cachedPages: cached.length
138
+ } });
139
+ }
140
+ this.scheduleRetry(sourceId);
141
+ }
142
+ }
143
+ for (const cachedId of this.lastGood.keys()) if (!seenIds.has(cachedId)) this.lastGood.delete(cachedId);
144
+ return dedupePages(out);
145
+ }
146
+ /**
147
+ * Schedule background re-call of `listPages()` on a source that just
148
+ * failed. Walks `RETRY_BACKOFF_MS` from index 0 — each successful
149
+ * call updates the cache and emits `AddonPageReady` so the admin UI
150
+ * invalidates its query. Stops on first success or after the schedule
151
+ * is exhausted.
152
+ */
153
+ scheduleRetry(sourceId, attempt = 0) {
154
+ if (attempt >= RETRY_BACKOFF_MS.length) return;
155
+ if (this.retryTimers.has(sourceId)) return;
156
+ const delayMs = RETRY_BACKOFF_MS[attempt] ?? RETRY_BACKOFF_MS[RETRY_BACKOFF_MS.length - 1];
157
+ const timer = setTimeout(() => {
158
+ this.retryTimers.delete(sourceId);
159
+ this.retrySource(sourceId, attempt);
160
+ }, delayMs);
161
+ this.retryTimers.set(sourceId, timer);
162
+ }
163
+ async retrySource(sourceId, attempt) {
164
+ const source = (this.capabilities?.getCollection("addon-pages-source") ?? []).find((s) => s.id === sourceId);
165
+ if (!source) return;
166
+ try {
167
+ const enriched = (await Promise.resolve(source.listPages())).map((page) => ({
168
+ addonId: source.id,
169
+ page,
170
+ bundleUrl: this.makeBundleUrl(source.id, page.bundle)
171
+ }));
172
+ this.lastGood.set(source.id, enriched);
173
+ this.ctx.logger.info("addon-pages-source recovered after retry", { meta: {
174
+ sourceId,
175
+ attempt: attempt + 1,
176
+ pages: enriched.length
177
+ } });
178
+ this.ctx.eventBus.emit({
179
+ id: randomUUID(),
180
+ timestamp: /* @__PURE__ */ new Date(),
181
+ source: {
182
+ type: "addon",
183
+ id: this.id
184
+ },
185
+ category: EventCategory.AddonPageReady,
186
+ data: {
187
+ addonId: sourceId,
188
+ recovered: true
189
+ }
190
+ });
191
+ } catch (err) {
192
+ this.ctx.logger.debug("addon-pages-source retry failed", { meta: {
193
+ sourceId,
194
+ attempt: attempt + 1,
195
+ error: errMsg(err)
196
+ } });
197
+ this.scheduleRetry(sourceId, attempt + 1);
198
+ }
199
+ }
200
+ /**
201
+ * Build `/api/addon-pages/<addonId>/<bundle>?v=<mtime>`. Falls back
202
+ * to `Date.now()` when the bundle path can't be stat'd (remote addon
203
+ * with no local file, addon not yet on disk, etc.) — the browser
204
+ * just gets a fresh URL on each call instead of cache-friendly mtime.
205
+ */
206
+ makeBundleUrl(addonId, bundle) {
207
+ const bundlePath = this.resolveBundlePath(addonId, bundle);
208
+ let mtime = Date.now();
209
+ if (bundlePath !== null) try {
210
+ mtime = fs.statSync(bundlePath).mtimeMs;
211
+ } catch {}
212
+ return `/api/addon-pages/${addonId}/${bundle}?v=${Math.floor(mtime)}`;
213
+ }
214
+ /**
215
+ * Resolve the local filesystem path for an addon's bundle. Mirrors
216
+ * `AddonPagesService.resolveBundle` (server-side), but without the
217
+ * existence / traversal checks — those still live on the server's
218
+ * static file route. We only need a stat-able path here for the
219
+ * `mtime` cache-buster.
220
+ */
221
+ resolveBundlePath(addonId, bundle) {
222
+ const paths = this.resolvedPaths;
223
+ if (!paths) return null;
224
+ const addonDistPath = path$1.join(paths.addonsDir, "@camstack", `addon-${addonId}`, "dist");
225
+ const resolvedBase = path$1.resolve(addonDistPath);
226
+ const resolvedFile = path$1.resolve(addonDistPath, bundle);
227
+ if (!resolvedFile.startsWith(resolvedBase + path$1.sep) && resolvedFile !== resolvedBase) return null;
228
+ return resolvedFile;
229
+ }
230
+ /**
231
+ * Read `server.dataPath` from the cluster yml-backed sections (same
232
+ * source the server uses at boot), then derive the addons directory
233
+ * from it. Falls back to `camstack-data/addons` when no settings API
234
+ * is available — agents and isolated tests don't see this addon, so
235
+ * the fallback is purely defensive.
236
+ */
237
+ async resolvePaths() {
238
+ const fallback = { addonsDir: path$1.resolve("camstack-data", "addons") };
239
+ if (!this.ctx.settings) return fallback;
240
+ try {
241
+ const server = await this.ctx.settings.getSection("server");
242
+ const dataPath = typeof server["dataPath"] === "string" && server["dataPath"] ? server["dataPath"] : "camstack-data";
243
+ return { addonsDir: path$1.resolve(dataPath, "addons") };
244
+ } catch (err) {
245
+ this.ctx.logger.debug("Failed to read server.dataPath — falling back", { meta: { error: errMsg(err) } });
246
+ return fallback;
247
+ }
248
+ }
249
+ };
250
+ //#endregion
251
+ export { AddonPagesAggregatorAddon, AddonPagesAggregatorAddon as default };
@@ -0,0 +1,6 @@
1
+ import { AddonPageInfo } from '@camstack/types';
2
+ /**
3
+ * Return a new list with duplicate `(addonId, page.id)` entries removed,
4
+ * preserving first-seen order. Pure — never mutates the input.
5
+ */
6
+ export declare function dedupePages(pages: readonly AddonPageInfo[]): readonly AddonPageInfo[];
@@ -0,0 +1 @@
1
+ export { AddonPagesAggregatorAddon, default } from './addon-pages-aggregator.addon.js';
@@ -0,0 +1,8 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ require("../../chunk-Cek0wNdY.js");
6
+ const require_builtins_addon_pages_aggregator_addon_pages_aggregator_addon = require("./addon-pages-aggregator.addon.js");
7
+ exports.AddonPagesAggregatorAddon = require_builtins_addon_pages_aggregator_addon_pages_aggregator_addon.AddonPagesAggregatorAddon;
8
+ exports.default = require_builtins_addon_pages_aggregator_addon_pages_aggregator_addon.AddonPagesAggregatorAddon;
@@ -0,0 +1,2 @@
1
+ import { AddonPagesAggregatorAddon } from "./addon-pages-aggregator.addon.mjs";
2
+ export { AddonPagesAggregatorAddon, AddonPagesAggregatorAddon as default };
@@ -0,0 +1,47 @@
1
+ import { BaseAddon, ProviderRegistration } from '@camstack/types';
2
+ export declare class AddonWidgetsAggregatorAddon extends BaseAddon {
3
+ readonly id = "addon-widgets-aggregator";
4
+ private resolvedPaths;
5
+ /**
6
+ * Last successful `listWidgets()` snapshot per source. Used as the
7
+ * "stale-but-valid" fallback when a source transiently fails — drops
8
+ * happen often enough during boot (Moleculer service-discovery
9
+ * window) that swallowing the error and returning empty would leave
10
+ * the dashboard with nothing for several seconds. Keeping the
11
+ * previous good entry means a flake is invisible to the operator.
12
+ */
13
+ private readonly lastGood;
14
+ /** In-flight retry guards keyed by sourceAddonId. Avoids double-scheduling. */
15
+ private readonly retryTimers;
16
+ constructor();
17
+ protected onInitialize(): Promise<ProviderRegistration[]>;
18
+ protected onShutdown(): Promise<void>;
19
+ /**
20
+ * Strip the `@<nodeId>` suffix that the CapabilityBridge appends to
21
+ * collection-provider registry keys for cross-node addons (see
22
+ * `moleculer.service.ts` — `registryKey = ${addonId}@${nodeId}`).
23
+ *
24
+ * The widget bundle is hub-resident (the same npm package ships to
25
+ * every node and the hub keeps a copy on disk keyed by the bare
26
+ * manifest id), so both the static-file URL and the admin-ui widget
27
+ * namespace must use the bare addon id. Without this, a widget
28
+ * source running on a remote agent yields a `bundleUrl` like
29
+ * `/api/addon-widgets/pipeline-analytics@agent-0/pipeline-analytics/remoteEntry.js`
30
+ * — the embedded `@<node>/<group>` makes the static-file route's
31
+ * `:addonId` param mismatch the registered provider and 404.
32
+ */
33
+ private bareAddonId;
34
+ private aggregate;
35
+ private scheduleRetry;
36
+ private retrySource;
37
+ /**
38
+ * Build `/api/addon-widgets/<addonId>/<bundle>?v=<mtime>`. Falls back
39
+ * to `Date.now()` when the bundle path can't be stat'd (remote addon
40
+ * with no local file, addon not yet on disk, etc.) — the browser
41
+ * just gets a fresh URL on each call instead of cache-friendly mtime.
42
+ */
43
+ private makeBundleUrl;
44
+ private resolveBundlePath;
45
+ private resolvePaths;
46
+ }
47
+ export default AddonWidgetsAggregatorAddon;
@@ -0,0 +1,228 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ const require_chunk = require("../../chunk-Cek0wNdY.js");
6
+ const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
7
+ let node_fs = require("node:fs");
8
+ node_fs = require_chunk.__toESM(node_fs);
9
+ let node_path = require("node:path");
10
+ node_path = require_chunk.__toESM(node_path);
11
+ let _camstack_types = require("@camstack/types");
12
+ let node_crypto = require("node:crypto");
13
+ //#region src/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.ts
14
+ /**
15
+ * Addon Widgets Aggregator — hub-local builtin that owns the singleton
16
+ * `addon-widgets` cap.
17
+ *
18
+ * Mirrors `addon-pages-aggregator` exactly: walks every registered
19
+ * `addon-widgets-source` (collection) provider and emits an enriched
20
+ * widget metadata list with versioned `bundleUrl`s pointing at
21
+ * `/api/addon-widgets/<addonId>/<bundle>?v=<mtime>`. The filesystem
22
+ * `mtime` cache-buster lets the browser pick up addon rebuilds without
23
+ * manual reload.
24
+ *
25
+ * The static file endpoint (`/api/addon-widgets/:addonId/*`) is served
26
+ * by `AddonWidgetsService.resolveBundle()` on the server side; this
27
+ * addon only owns the listing surface.
28
+ *
29
+ * Why a builtin: same reasoning as `addon-pages-aggregator`. The
30
+ * aggregator is the de-facto "addon-widgets provider" — addons own caps,
31
+ * not the server. Living in `@camstack/system/builtins` keeps the surface
32
+ * symmetrical with `system-config`, `local-auth`, etc.
33
+ */
34
+ /**
35
+ * Backoff schedule (ms) used to retry sources that failed during a
36
+ * `listWidgets()` round-trip — typically because the cap was just
37
+ * registered (provider connected via Moleculer) but the worker-side
38
+ * action registration hadn't propagated yet, so `Service '...listWidgets'
39
+ * is not found on '<node>'` raced ahead of the call.
40
+ *
41
+ * On success we re-emit `AddonWidgetReady` so admin-ui invalidates its
42
+ * `addonWidgets.listWidgets` query and the registry populates without a
43
+ * page reload.
44
+ */
45
+ var RETRY_BACKOFF_MS = [
46
+ 500,
47
+ 1500,
48
+ 4e3
49
+ ];
50
+ /**
51
+ * Per-source ceiling for a single `listWidgets()` round-trip. Mirrors the
52
+ * addon-pages aggregator: a slow/unreachable source (e.g. an agent-hosted
53
+ * widget source whose cap call sits in a Moleculer `waitForServices`) times
54
+ * out fast and serves its cached snapshot instead of blocking the dashboard.
55
+ */
56
+ var PER_SOURCE_TIMEOUT_MS = 2500;
57
+ var AddonWidgetsAggregatorAddon = class extends _camstack_types.BaseAddon {
58
+ id = "addon-widgets-aggregator";
59
+ resolvedPaths = null;
60
+ /**
61
+ * Last successful `listWidgets()` snapshot per source. Used as the
62
+ * "stale-but-valid" fallback when a source transiently fails — drops
63
+ * happen often enough during boot (Moleculer service-discovery
64
+ * window) that swallowing the error and returning empty would leave
65
+ * the dashboard with nothing for several seconds. Keeping the
66
+ * previous good entry means a flake is invisible to the operator.
67
+ */
68
+ lastGood = /* @__PURE__ */ new Map();
69
+ /** In-flight retry guards keyed by sourceAddonId. Avoids double-scheduling. */
70
+ retryTimers = /* @__PURE__ */ new Map();
71
+ constructor() {
72
+ super({});
73
+ }
74
+ async onInitialize() {
75
+ this.resolvedPaths = await this.resolvePaths();
76
+ const provider = { listWidgets: async () => this.aggregate() };
77
+ this.ctx.logger.info("Initialized — aggregating addon-widgets-source providers");
78
+ return [{
79
+ capability: _camstack_types.addonWidgetsCapability,
80
+ provider
81
+ }];
82
+ }
83
+ async onShutdown() {
84
+ for (const t of this.retryTimers.values()) clearTimeout(t);
85
+ this.retryTimers.clear();
86
+ this.lastGood.clear();
87
+ }
88
+ /**
89
+ * Strip the `@<nodeId>` suffix that the CapabilityBridge appends to
90
+ * collection-provider registry keys for cross-node addons (see
91
+ * `moleculer.service.ts` — `registryKey = ${addonId}@${nodeId}`).
92
+ *
93
+ * The widget bundle is hub-resident (the same npm package ships to
94
+ * every node and the hub keeps a copy on disk keyed by the bare
95
+ * manifest id), so both the static-file URL and the admin-ui widget
96
+ * namespace must use the bare addon id. Without this, a widget
97
+ * source running on a remote agent yields a `bundleUrl` like
98
+ * `/api/addon-widgets/pipeline-analytics@agent-0/pipeline-analytics/remoteEntry.js`
99
+ * — the embedded `@<node>/<group>` makes the static-file route's
100
+ * `:addonId` param mismatch the registered provider and 404.
101
+ */
102
+ bareAddonId(registryKey) {
103
+ const at = registryKey.indexOf("@");
104
+ return at === -1 ? registryKey : registryKey.slice(0, at);
105
+ }
106
+ async aggregate() {
107
+ const entries = this.capabilities?.getCollectionEntries("addon-widgets-source") ?? [];
108
+ const out = [];
109
+ const seenIds = /* @__PURE__ */ new Set();
110
+ const settled = await require_settle_sources.settleSourcesWithTimeout(entries.map(([registryKey, source]) => [registryKey, () => Promise.resolve(source.listWidgets())]), PER_SOURCE_TIMEOUT_MS);
111
+ for (const [addonId, result] of settled) {
112
+ const publicAddonId = this.bareAddonId(addonId);
113
+ seenIds.add(addonId);
114
+ if (result.ok) {
115
+ const enriched = result.value.map((w) => ({
116
+ ...w,
117
+ addonId: publicAddonId,
118
+ bundleUrl: this.makeBundleUrl(publicAddonId, w.bundle)
119
+ }));
120
+ for (const item of enriched) out.push(item);
121
+ this.lastGood.set(addonId, enriched);
122
+ } else {
123
+ this.ctx.logger.warn("addon-widgets-source provider failed", { meta: {
124
+ sourceId: addonId,
125
+ error: result.error.message
126
+ } });
127
+ const cached = this.lastGood.get(addonId);
128
+ if (cached !== void 0) {
129
+ for (const item of cached) out.push(item);
130
+ this.ctx.logger.info("addon-widgets-source falling back to cached snapshot", { meta: {
131
+ sourceId: addonId,
132
+ cachedWidgets: cached.length
133
+ } });
134
+ }
135
+ this.scheduleRetry(addonId);
136
+ }
137
+ }
138
+ for (const cachedId of this.lastGood.keys()) if (!seenIds.has(cachedId)) this.lastGood.delete(cachedId);
139
+ return out;
140
+ }
141
+ scheduleRetry(sourceId, attempt = 0) {
142
+ if (attempt >= RETRY_BACKOFF_MS.length) return;
143
+ if (this.retryTimers.has(sourceId)) return;
144
+ const delayMs = RETRY_BACKOFF_MS[attempt] ?? RETRY_BACKOFF_MS[RETRY_BACKOFF_MS.length - 1];
145
+ const timer = setTimeout(() => {
146
+ this.retryTimers.delete(sourceId);
147
+ this.retrySource(sourceId, attempt);
148
+ }, delayMs);
149
+ this.retryTimers.set(sourceId, timer);
150
+ }
151
+ async retrySource(sourceId, attempt) {
152
+ const found = (this.capabilities?.getCollectionEntries("addon-widgets-source") ?? []).find(([id]) => id === sourceId);
153
+ if (!found) return;
154
+ const [addonId, source] = found;
155
+ const publicAddonId = this.bareAddonId(addonId);
156
+ try {
157
+ const enriched = (await Promise.resolve(source.listWidgets())).map((w) => ({
158
+ ...w,
159
+ addonId: publicAddonId,
160
+ bundleUrl: this.makeBundleUrl(publicAddonId, w.bundle)
161
+ }));
162
+ this.lastGood.set(addonId, enriched);
163
+ this.ctx.logger.info("addon-widgets-source recovered after retry", { meta: {
164
+ sourceId: addonId,
165
+ attempt: attempt + 1,
166
+ widgets: enriched.length
167
+ } });
168
+ this.ctx.eventBus.emit({
169
+ id: (0, node_crypto.randomUUID)(),
170
+ timestamp: /* @__PURE__ */ new Date(),
171
+ source: {
172
+ type: "addon",
173
+ id: this.id
174
+ },
175
+ category: _camstack_types.EventCategory.AddonWidgetReady,
176
+ data: {
177
+ addonId: publicAddonId,
178
+ recovered: true
179
+ }
180
+ });
181
+ } catch (err) {
182
+ this.ctx.logger.debug("addon-widgets-source retry failed", { meta: {
183
+ sourceId,
184
+ attempt: attempt + 1,
185
+ error: (0, _camstack_types.errMsg)(err)
186
+ } });
187
+ this.scheduleRetry(sourceId, attempt + 1);
188
+ }
189
+ }
190
+ /**
191
+ * Build `/api/addon-widgets/<addonId>/<bundle>?v=<mtime>`. Falls back
192
+ * to `Date.now()` when the bundle path can't be stat'd (remote addon
193
+ * with no local file, addon not yet on disk, etc.) — the browser
194
+ * just gets a fresh URL on each call instead of cache-friendly mtime.
195
+ */
196
+ makeBundleUrl(addonId, bundle) {
197
+ const bundlePath = this.resolveBundlePath(addonId, bundle);
198
+ let mtime = Date.now();
199
+ if (bundlePath !== null) try {
200
+ mtime = node_fs.statSync(bundlePath).mtimeMs;
201
+ } catch {}
202
+ return `/api/addon-widgets/${addonId}/${bundle}?v=${Math.floor(mtime)}`;
203
+ }
204
+ resolveBundlePath(addonId, bundle) {
205
+ const paths = this.resolvedPaths;
206
+ if (!paths) return null;
207
+ const addonDistPath = node_path.join(paths.addonsDir, "@camstack", `addon-${addonId}`, "dist");
208
+ const resolvedBase = node_path.resolve(addonDistPath);
209
+ const resolvedFile = node_path.resolve(addonDistPath, bundle);
210
+ if (!resolvedFile.startsWith(resolvedBase + node_path.sep) && resolvedFile !== resolvedBase) return null;
211
+ return resolvedFile;
212
+ }
213
+ async resolvePaths() {
214
+ const fallback = { addonsDir: node_path.resolve("camstack-data", "addons") };
215
+ if (!this.ctx.settings) return fallback;
216
+ try {
217
+ const server = await this.ctx.settings.getSection("server");
218
+ const dataPath = typeof server["dataPath"] === "string" && server["dataPath"] ? server["dataPath"] : "camstack-data";
219
+ return { addonsDir: node_path.resolve(dataPath, "addons") };
220
+ } catch (err) {
221
+ this.ctx.logger.debug("Failed to read server.dataPath — falling back", { meta: { error: (0, _camstack_types.errMsg)(err) } });
222
+ return fallback;
223
+ }
224
+ }
225
+ };
226
+ //#endregion
227
+ exports.AddonWidgetsAggregatorAddon = AddonWidgetsAggregatorAddon;
228
+ exports.default = AddonWidgetsAggregatorAddon;