@bleedingdev/modern-js-server-core 3.2.0-ultramodern.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.
Files changed (291) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +26 -0
  3. package/dist/cjs/adapters/node/helper/index.js +55 -0
  4. package/dist/cjs/adapters/node/helper/loadCache.js +58 -0
  5. package/dist/cjs/adapters/node/helper/loadConfig.js +78 -0
  6. package/dist/cjs/adapters/node/helper/loadEnv.js +66 -0
  7. package/dist/cjs/adapters/node/helper/loadPlugin.js +47 -0
  8. package/dist/cjs/adapters/node/helper/utils.js +39 -0
  9. package/dist/cjs/adapters/node/hono.js +95 -0
  10. package/dist/cjs/adapters/node/index.js +87 -0
  11. package/dist/cjs/adapters/node/node.js +180 -0
  12. package/dist/cjs/adapters/node/plugins/index.js +72 -0
  13. package/dist/cjs/adapters/node/plugins/nodeServer.js +43 -0
  14. package/dist/cjs/adapters/node/plugins/resource.js +206 -0
  15. package/dist/cjs/adapters/node/plugins/static.js +379 -0
  16. package/dist/cjs/constants.js +77 -0
  17. package/dist/cjs/context.js +41 -0
  18. package/dist/cjs/helper.js +45 -0
  19. package/dist/cjs/hono.js +46 -0
  20. package/dist/cjs/index.js +247 -0
  21. package/dist/cjs/plugins/compat/hooks.js +80 -0
  22. package/dist/cjs/plugins/compat/index.js +64 -0
  23. package/dist/cjs/plugins/contractGateAutopilot.js +158 -0
  24. package/dist/cjs/plugins/contractGateSnapshotStore.js +239 -0
  25. package/dist/cjs/plugins/default.js +61 -0
  26. package/dist/cjs/plugins/favicon.js +48 -0
  27. package/dist/cjs/plugins/index.js +157 -0
  28. package/dist/cjs/plugins/log.js +92 -0
  29. package/dist/cjs/plugins/mfCache.js +78 -0
  30. package/dist/cjs/plugins/middlewares.js +49 -0
  31. package/dist/cjs/plugins/monitors.js +192 -0
  32. package/dist/cjs/plugins/processedBy.js +50 -0
  33. package/dist/cjs/plugins/render/csrRscRender.js +74 -0
  34. package/dist/cjs/plugins/render/dataHandler.js +53 -0
  35. package/dist/cjs/plugins/render/index.js +158 -0
  36. package/dist/cjs/plugins/render/inject.js +92 -0
  37. package/dist/cjs/plugins/render/render.js +273 -0
  38. package/dist/cjs/plugins/render/renderRscHandler.js +72 -0
  39. package/dist/cjs/plugins/render/serverActionHandler.js +47 -0
  40. package/dist/cjs/plugins/render/ssrCache.js +198 -0
  41. package/dist/cjs/plugins/render/ssrRender.js +96 -0
  42. package/dist/cjs/plugins/render/utils.js +49 -0
  43. package/dist/cjs/plugins/route.js +68 -0
  44. package/dist/cjs/plugins/telemetry.js +1283 -0
  45. package/dist/cjs/serverBase.js +176 -0
  46. package/dist/cjs/types/config/bff.js +18 -0
  47. package/dist/cjs/types/config/dev.js +18 -0
  48. package/dist/cjs/types/config/html.js +18 -0
  49. package/dist/cjs/types/config/index.js +93 -0
  50. package/dist/cjs/types/config/output.js +18 -0
  51. package/dist/cjs/types/config/security.js +18 -0
  52. package/dist/cjs/types/config/server.js +18 -0
  53. package/dist/cjs/types/config/share.js +18 -0
  54. package/dist/cjs/types/config/source.js +18 -0
  55. package/dist/cjs/types/config/tools.js +18 -0
  56. package/dist/cjs/types/index.js +79 -0
  57. package/dist/cjs/types/plugins/base.js +18 -0
  58. package/dist/cjs/types/plugins/index.js +58 -0
  59. package/dist/cjs/types/plugins/plugin.js +18 -0
  60. package/dist/cjs/types/render.js +18 -0
  61. package/dist/cjs/types/requestHandler.js +18 -0
  62. package/dist/cjs/types/server.js +18 -0
  63. package/dist/cjs/utils/entry.js +40 -0
  64. package/dist/cjs/utils/env.js +51 -0
  65. package/dist/cjs/utils/error.js +93 -0
  66. package/dist/cjs/utils/index.js +114 -0
  67. package/dist/cjs/utils/middlewareCollector.js +63 -0
  68. package/dist/cjs/utils/publicDir.js +92 -0
  69. package/dist/cjs/utils/request.js +86 -0
  70. package/dist/cjs/utils/serverConfig.js +43 -0
  71. package/dist/cjs/utils/storage.js +69 -0
  72. package/dist/cjs/utils/transformStream.js +65 -0
  73. package/dist/cjs/utils/warmup.js +40 -0
  74. package/dist/esm/adapters/node/helper/index.mjs +5 -0
  75. package/dist/esm/adapters/node/helper/loadCache.mjs +14 -0
  76. package/dist/esm/adapters/node/helper/loadConfig.mjs +31 -0
  77. package/dist/esm/adapters/node/helper/loadEnv.mjs +22 -0
  78. package/dist/esm/adapters/node/helper/loadPlugin.mjs +13 -0
  79. package/dist/esm/adapters/node/helper/utils.mjs +5 -0
  80. package/dist/esm/adapters/node/hono.mjs +55 -0
  81. package/dist/esm/adapters/node/index.mjs +4 -0
  82. package/dist/esm/adapters/node/node.mjs +130 -0
  83. package/dist/esm/adapters/node/plugins/index.mjs +3 -0
  84. package/dist/esm/adapters/node/plugins/nodeServer.mjs +9 -0
  85. package/dist/esm/adapters/node/plugins/resource.mjs +138 -0
  86. package/dist/esm/adapters/node/plugins/static.mjs +329 -0
  87. package/dist/esm/constants.mjs +28 -0
  88. package/dist/esm/context.mjs +4 -0
  89. package/dist/esm/helper.mjs +11 -0
  90. package/dist/esm/hono.mjs +2 -0
  91. package/dist/esm/index.mjs +12 -0
  92. package/dist/esm/plugins/compat/hooks.mjs +40 -0
  93. package/dist/esm/plugins/compat/index.mjs +27 -0
  94. package/dist/esm/plugins/contractGateAutopilot.mjs +124 -0
  95. package/dist/esm/plugins/contractGateSnapshotStore.mjs +180 -0
  96. package/dist/esm/plugins/default.mjs +27 -0
  97. package/dist/esm/plugins/favicon.mjs +14 -0
  98. package/dist/esm/plugins/index.mjs +11 -0
  99. package/dist/esm/plugins/log.mjs +58 -0
  100. package/dist/esm/plugins/mfCache.mjs +35 -0
  101. package/dist/esm/plugins/middlewares.mjs +15 -0
  102. package/dist/esm/plugins/monitors.mjs +149 -0
  103. package/dist/esm/plugins/processedBy.mjs +16 -0
  104. package/dist/esm/plugins/render/csrRscRender.mjs +40 -0
  105. package/dist/esm/plugins/render/dataHandler.mjs +19 -0
  106. package/dist/esm/plugins/render/index.mjs +84 -0
  107. package/dist/esm/plugins/render/inject.mjs +55 -0
  108. package/dist/esm/plugins/render/render.mjs +230 -0
  109. package/dist/esm/plugins/render/renderRscHandler.mjs +38 -0
  110. package/dist/esm/plugins/render/serverActionHandler.mjs +13 -0
  111. package/dist/esm/plugins/render/ssrCache.mjs +158 -0
  112. package/dist/esm/plugins/render/ssrRender.mjs +62 -0
  113. package/dist/esm/plugins/render/utils.mjs +15 -0
  114. package/dist/esm/plugins/route.mjs +34 -0
  115. package/dist/esm/plugins/telemetry.mjs +1195 -0
  116. package/dist/esm/rslib-runtime.mjs +18 -0
  117. package/dist/esm/serverBase.mjs +139 -0
  118. package/dist/esm/types/config/bff.mjs +0 -0
  119. package/dist/esm/types/config/dev.mjs +0 -0
  120. package/dist/esm/types/config/html.mjs +0 -0
  121. package/dist/esm/types/config/index.mjs +6 -0
  122. package/dist/esm/types/config/output.mjs +0 -0
  123. package/dist/esm/types/config/security.mjs +0 -0
  124. package/dist/esm/types/config/server.mjs +0 -0
  125. package/dist/esm/types/config/share.mjs +0 -0
  126. package/dist/esm/types/config/source.mjs +0 -0
  127. package/dist/esm/types/config/tools.mjs +0 -0
  128. package/dist/esm/types/index.mjs +4 -0
  129. package/dist/esm/types/plugins/base.mjs +0 -0
  130. package/dist/esm/types/plugins/index.mjs +1 -0
  131. package/dist/esm/types/plugins/plugin.mjs +0 -0
  132. package/dist/esm/types/render.mjs +0 -0
  133. package/dist/esm/types/requestHandler.mjs +0 -0
  134. package/dist/esm/types/server.mjs +0 -0
  135. package/dist/esm/utils/entry.mjs +3 -0
  136. package/dist/esm/utils/env.mjs +14 -0
  137. package/dist/esm/utils/error.mjs +53 -0
  138. package/dist/esm/utils/index.mjs +9 -0
  139. package/dist/esm/utils/middlewareCollector.mjs +26 -0
  140. package/dist/esm/utils/publicDir.mjs +33 -0
  141. package/dist/esm/utils/request.mjs +40 -0
  142. package/dist/esm/utils/serverConfig.mjs +9 -0
  143. package/dist/esm/utils/storage.mjs +35 -0
  144. package/dist/esm/utils/transformStream.mjs +28 -0
  145. package/dist/esm/utils/warmup.mjs +6 -0
  146. package/dist/esm-node/adapters/node/helper/index.mjs +6 -0
  147. package/dist/esm-node/adapters/node/helper/loadCache.mjs +15 -0
  148. package/dist/esm-node/adapters/node/helper/loadConfig.mjs +32 -0
  149. package/dist/esm-node/adapters/node/helper/loadEnv.mjs +23 -0
  150. package/dist/esm-node/adapters/node/helper/loadPlugin.mjs +14 -0
  151. package/dist/esm-node/adapters/node/helper/utils.mjs +6 -0
  152. package/dist/esm-node/adapters/node/hono.mjs +56 -0
  153. package/dist/esm-node/adapters/node/index.mjs +5 -0
  154. package/dist/esm-node/adapters/node/node.mjs +131 -0
  155. package/dist/esm-node/adapters/node/plugins/index.mjs +4 -0
  156. package/dist/esm-node/adapters/node/plugins/nodeServer.mjs +10 -0
  157. package/dist/esm-node/adapters/node/plugins/resource.mjs +139 -0
  158. package/dist/esm-node/adapters/node/plugins/static.mjs +330 -0
  159. package/dist/esm-node/constants.mjs +29 -0
  160. package/dist/esm-node/context.mjs +5 -0
  161. package/dist/esm-node/helper.mjs +12 -0
  162. package/dist/esm-node/hono.mjs +3 -0
  163. package/dist/esm-node/index.mjs +13 -0
  164. package/dist/esm-node/plugins/compat/hooks.mjs +41 -0
  165. package/dist/esm-node/plugins/compat/index.mjs +28 -0
  166. package/dist/esm-node/plugins/contractGateAutopilot.mjs +125 -0
  167. package/dist/esm-node/plugins/contractGateSnapshotStore.mjs +182 -0
  168. package/dist/esm-node/plugins/default.mjs +28 -0
  169. package/dist/esm-node/plugins/favicon.mjs +15 -0
  170. package/dist/esm-node/plugins/index.mjs +12 -0
  171. package/dist/esm-node/plugins/log.mjs +59 -0
  172. package/dist/esm-node/plugins/mfCache.mjs +36 -0
  173. package/dist/esm-node/plugins/middlewares.mjs +16 -0
  174. package/dist/esm-node/plugins/monitors.mjs +150 -0
  175. package/dist/esm-node/plugins/processedBy.mjs +17 -0
  176. package/dist/esm-node/plugins/render/csrRscRender.mjs +41 -0
  177. package/dist/esm-node/plugins/render/dataHandler.mjs +20 -0
  178. package/dist/esm-node/plugins/render/index.mjs +85 -0
  179. package/dist/esm-node/plugins/render/inject.mjs +56 -0
  180. package/dist/esm-node/plugins/render/render.mjs +231 -0
  181. package/dist/esm-node/plugins/render/renderRscHandler.mjs +39 -0
  182. package/dist/esm-node/plugins/render/serverActionHandler.mjs +14 -0
  183. package/dist/esm-node/plugins/render/ssrCache.mjs +159 -0
  184. package/dist/esm-node/plugins/render/ssrRender.mjs +63 -0
  185. package/dist/esm-node/plugins/render/utils.mjs +16 -0
  186. package/dist/esm-node/plugins/route.mjs +35 -0
  187. package/dist/esm-node/plugins/telemetry.mjs +1196 -0
  188. package/dist/esm-node/rslib-runtime.mjs +19 -0
  189. package/dist/esm-node/serverBase.mjs +140 -0
  190. package/dist/esm-node/types/config/bff.mjs +1 -0
  191. package/dist/esm-node/types/config/dev.mjs +1 -0
  192. package/dist/esm-node/types/config/html.mjs +1 -0
  193. package/dist/esm-node/types/config/index.mjs +7 -0
  194. package/dist/esm-node/types/config/output.mjs +1 -0
  195. package/dist/esm-node/types/config/security.mjs +1 -0
  196. package/dist/esm-node/types/config/server.mjs +1 -0
  197. package/dist/esm-node/types/config/share.mjs +1 -0
  198. package/dist/esm-node/types/config/source.mjs +1 -0
  199. package/dist/esm-node/types/config/tools.mjs +1 -0
  200. package/dist/esm-node/types/index.mjs +5 -0
  201. package/dist/esm-node/types/plugins/base.mjs +1 -0
  202. package/dist/esm-node/types/plugins/index.mjs +2 -0
  203. package/dist/esm-node/types/plugins/plugin.mjs +1 -0
  204. package/dist/esm-node/types/render.mjs +1 -0
  205. package/dist/esm-node/types/requestHandler.mjs +1 -0
  206. package/dist/esm-node/types/server.mjs +1 -0
  207. package/dist/esm-node/utils/entry.mjs +4 -0
  208. package/dist/esm-node/utils/env.mjs +15 -0
  209. package/dist/esm-node/utils/error.mjs +54 -0
  210. package/dist/esm-node/utils/index.mjs +10 -0
  211. package/dist/esm-node/utils/middlewareCollector.mjs +27 -0
  212. package/dist/esm-node/utils/publicDir.mjs +34 -0
  213. package/dist/esm-node/utils/request.mjs +41 -0
  214. package/dist/esm-node/utils/serverConfig.mjs +10 -0
  215. package/dist/esm-node/utils/storage.mjs +36 -0
  216. package/dist/esm-node/utils/transformStream.mjs +29 -0
  217. package/dist/esm-node/utils/warmup.mjs +7 -0
  218. package/dist/types/adapters/node/helper/index.d.ts +6 -0
  219. package/dist/types/adapters/node/helper/loadCache.d.ts +2 -0
  220. package/dist/types/adapters/node/helper/loadConfig.d.ts +3 -0
  221. package/dist/types/adapters/node/helper/loadEnv.d.ts +3 -0
  222. package/dist/types/adapters/node/helper/loadPlugin.d.ts +3 -0
  223. package/dist/types/adapters/node/helper/utils.d.ts +21 -0
  224. package/dist/types/adapters/node/hono.d.ts +19 -0
  225. package/dist/types/adapters/node/index.d.ts +5 -0
  226. package/dist/types/adapters/node/node.d.ts +17 -0
  227. package/dist/types/adapters/node/plugins/index.d.ts +3 -0
  228. package/dist/types/adapters/node/plugins/nodeServer.d.ts +6 -0
  229. package/dist/types/adapters/node/plugins/resource.d.ts +11 -0
  230. package/dist/types/adapters/node/plugins/static.d.ts +25 -0
  231. package/dist/types/constants.d.ts +26 -0
  232. package/dist/types/context.d.ts +3 -0
  233. package/dist/types/helper.d.ts +10 -0
  234. package/dist/types/hono.d.ts +3 -0
  235. package/dist/types/index.d.ts +14 -0
  236. package/dist/types/plugins/compat/hooks.d.ts +8 -0
  237. package/dist/types/plugins/compat/index.d.ts +3 -0
  238. package/dist/types/plugins/contractGateAutopilot.d.ts +35 -0
  239. package/dist/types/plugins/contractGateSnapshotStore.d.ts +57 -0
  240. package/dist/types/plugins/default.d.ts +7 -0
  241. package/dist/types/plugins/favicon.d.ts +2 -0
  242. package/dist/types/plugins/index.d.ts +11 -0
  243. package/dist/types/plugins/log.d.ts +2 -0
  244. package/dist/types/plugins/mfCache.d.ts +12 -0
  245. package/dist/types/plugins/middlewares.d.ts +2 -0
  246. package/dist/types/plugins/monitors.d.ts +6 -0
  247. package/dist/types/plugins/processedBy.d.ts +2 -0
  248. package/dist/types/plugins/render/csrRscRender.d.ts +2 -0
  249. package/dist/types/plugins/render/dataHandler.d.ts +5 -0
  250. package/dist/types/plugins/render/index.d.ts +3 -0
  251. package/dist/types/plugins/render/inject.d.ts +7 -0
  252. package/dist/types/plugins/render/render.d.ts +16 -0
  253. package/dist/types/plugins/render/renderRscHandler.d.ts +2 -0
  254. package/dist/types/plugins/render/serverActionHandler.d.ts +2 -0
  255. package/dist/types/plugins/render/ssrCache.d.ts +18 -0
  256. package/dist/types/plugins/render/ssrRender.d.ts +26 -0
  257. package/dist/types/plugins/render/utils.d.ts +3 -0
  258. package/dist/types/plugins/route.d.ts +2 -0
  259. package/dist/types/plugins/telemetry.d.ts +309 -0
  260. package/dist/types/serverBase.d.ts +38 -0
  261. package/dist/types/types/config/bff.d.ts +142 -0
  262. package/dist/types/types/config/dev.d.ts +4 -0
  263. package/dist/types/types/config/html.d.ts +15 -0
  264. package/dist/types/types/config/index.d.ts +35 -0
  265. package/dist/types/types/config/output.d.ts +20 -0
  266. package/dist/types/types/config/security.d.ts +4 -0
  267. package/dist/types/types/config/server.d.ts +402 -0
  268. package/dist/types/types/config/share.d.ts +3 -0
  269. package/dist/types/types/config/source.d.ts +7 -0
  270. package/dist/types/types/config/tools.d.ts +2 -0
  271. package/dist/types/types/index.d.ts +4 -0
  272. package/dist/types/types/plugins/base.d.ts +57 -0
  273. package/dist/types/types/plugins/index.d.ts +2 -0
  274. package/dist/types/types/plugins/plugin.d.ts +31 -0
  275. package/dist/types/types/render.d.ts +24 -0
  276. package/dist/types/types/requestHandler.d.ts +48 -0
  277. package/dist/types/types/server.d.ts +67 -0
  278. package/dist/types/utils/entry.d.ts +3 -0
  279. package/dist/types/utils/env.d.ts +2 -0
  280. package/dist/types/utils/error.d.ts +8 -0
  281. package/dist/types/utils/index.d.ts +9 -0
  282. package/dist/types/utils/middlewareCollector.d.ts +12 -0
  283. package/dist/types/utils/publicDir.d.ts +40 -0
  284. package/dist/types/utils/request.d.ts +17 -0
  285. package/dist/types/utils/serverConfig.d.ts +8 -0
  286. package/dist/types/utils/storage.d.ts +5 -0
  287. package/dist/types/utils/transformStream.d.ts +5 -0
  288. package/dist/types/utils/warmup.d.ts +1 -0
  289. package/package.json +103 -0
  290. package/rslib.config.mts +4 -0
  291. package/rstest.config.mts +7 -0
@@ -0,0 +1,1283 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ DEFAULT_RUNTIME_FALLBACK_SIGNAL_ENDPOINT: ()=>DEFAULT_RUNTIME_FALLBACK_SIGNAL_ENDPOINT,
28
+ DEFAULT_RUNTIME_STATUS_ENDPOINT: ()=>DEFAULT_RUNTIME_STATUS_ENDPOINT,
29
+ TelemetryCanaryOrchestrator: ()=>TelemetryCanaryOrchestrator,
30
+ TelemetryRegistry: ()=>TelemetryRegistry,
31
+ TelemetryStartupHealthError: ()=>TelemetryStartupHealthError,
32
+ createOtlpTelemetryExporter: ()=>createOtlpTelemetryExporter,
33
+ createRuntimeFallbackSignalRuntimeState: ()=>createRuntimeFallbackSignalRuntimeState,
34
+ createRuntimeSignalError: ()=>createRuntimeSignalError,
35
+ createTelemetryAwareMetrics: ()=>createTelemetryAwareMetrics,
36
+ createVictoriaMetricsTelemetryExporter: ()=>createVictoriaMetricsTelemetryExporter,
37
+ enforceRuntimeFallbackSignalAuthToken: ()=>enforceRuntimeFallbackSignalAuthToken,
38
+ enforceRuntimeFallbackSignalTrustPolicy: ()=>enforceRuntimeFallbackSignalTrustPolicy,
39
+ getRuntimeSignalErrorStatusCode: ()=>getRuntimeSignalErrorStatusCode,
40
+ hasEnabledTelemetryExporters: ()=>hasEnabledTelemetryExporters,
41
+ injectTelemetryPlugin: ()=>injectTelemetryPlugin,
42
+ normalizeRuntimeFallbackSignalAuthConfig: ()=>normalizeRuntimeFallbackSignalAuthConfig,
43
+ normalizeRuntimeFallbackTrustPolicy: ()=>normalizeRuntimeFallbackTrustPolicy,
44
+ parseRuntimeFallbackSignalPayloadFromRawBody: ()=>parseRuntimeFallbackSignalPayloadFromRawBody,
45
+ resolveRuntimeFallbackSignalEndpoint: ()=>resolveRuntimeFallbackSignalEndpoint
46
+ });
47
+ const external_contractGateAutopilot_js_namespaceObject = require("./contractGateAutopilot.js");
48
+ const external_contractGateSnapshotStore_js_namespaceObject = require("./contractGateSnapshotStore.js");
49
+ class TelemetryStartupHealthError extends Error {
50
+ constructor(failedExporters){
51
+ super(`Telemetry startup health check failed for exporters: ${failedExporters.map((item)=>item.name).join(', ')}`), this.code = 'TELEMETRY_EXPORTER_STARTUP_HEALTH_FAILED';
52
+ this.name = 'TelemetryStartupHealthError';
53
+ this.failedExporters = failedExporters;
54
+ }
55
+ }
56
+ const TRACEPARENT_REGEX = /^00-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/i;
57
+ const DEFAULT_OTLP_ENDPOINT = 'http://127.0.0.1:4318/v1/logs';
58
+ const DEFAULT_VM_ENDPOINT = 'http://127.0.0.1:8428/api/v1/import/prometheus';
59
+ const DEFAULT_TIMEOUT_MS = 5000;
60
+ const DEFAULT_RUNTIME_FALLBACK_SIGNAL_ENDPOINT = '/_modern/contract-gates/runtime-fallback';
61
+ const DEFAULT_RUNTIME_STATUS_ENDPOINT = '/_modern/runtime/status';
62
+ const DEFAULT_RUNTIME_FALLBACK_GATE_NAME = 'runtime-mf-fallback-health';
63
+ const DEFAULT_RUNTIME_FALLBACK_FAILURE_HOLD_MS = 300000;
64
+ const DEFAULT_RUNTIME_FALLBACK_MAX_BODY_BYTES = 16384;
65
+ const DEFAULT_RUNTIME_FALLBACK_AUTH_HEADER = 'x-modernjs-runtime-signal-token';
66
+ const DEFAULT_RUNTIME_FALLBACK_TRUST_MAX_SIGNALS_PER_WINDOW = 30;
67
+ const DEFAULT_RUNTIME_FALLBACK_TRUST_WINDOW_MS = 60000;
68
+ const DEFAULT_RUNTIME_FALLBACK_TRUST_DEDUPE_WINDOW_MS = 10000;
69
+ function clamp(value, min, max) {
70
+ return Math.max(min, Math.min(max, value));
71
+ }
72
+ function isRecord(value) {
73
+ return 'object' == typeof value && null !== value && !Array.isArray(value);
74
+ }
75
+ function redactObject(value, redactionKeys) {
76
+ if (!isRecord(value)) return;
77
+ const output = {};
78
+ for (const [key, nested] of Object.entries(value)){
79
+ if (redactionKeys.has(key)) {
80
+ output[key] = '[REDACTED]';
81
+ continue;
82
+ }
83
+ if (Array.isArray(nested)) {
84
+ output[key] = nested.map((item)=>{
85
+ if (isRecord(item)) return redactObject(item, redactionKeys);
86
+ return item;
87
+ });
88
+ continue;
89
+ }
90
+ if (isRecord(nested)) {
91
+ output[key] = redactObject(nested, redactionKeys);
92
+ continue;
93
+ }
94
+ output[key] = nested;
95
+ }
96
+ return output;
97
+ }
98
+ function normalizeLabels(labels) {
99
+ if (!labels) return;
100
+ const normalized = {};
101
+ for (const [key, value] of Object.entries(labels))if (null != value) normalized[key] = String(value);
102
+ return Object.keys(normalized).length > 0 ? normalized : void 0;
103
+ }
104
+ function parseTraceparent(header) {
105
+ if (!header) return;
106
+ const match = header.trim().match(TRACEPARENT_REGEX);
107
+ if (!match) return;
108
+ const traceId = match[1]?.toLowerCase();
109
+ const spanId = match[2]?.toLowerCase();
110
+ if (!traceId || !spanId) return;
111
+ return {
112
+ traceId,
113
+ spanId
114
+ };
115
+ }
116
+ function extractError(args) {
117
+ for (const arg of args)if (arg instanceof Error) return {
118
+ name: arg.name,
119
+ message: arg.message,
120
+ stack: arg.stack
121
+ };
122
+ }
123
+ function toTelemetryEnvelope(event, input) {
124
+ const base = {
125
+ timestamp: Date.now(),
126
+ service: input.service,
127
+ module: input.module,
128
+ environment: input.environment,
129
+ ...input.traceId ? {
130
+ traceId: input.traceId
131
+ } : {},
132
+ ...input.spanId ? {
133
+ spanId: input.spanId
134
+ } : {},
135
+ ...input.attributes ? {
136
+ attributes: input.attributes
137
+ } : {}
138
+ };
139
+ if ('log' === event.type) {
140
+ const payload = event.payload;
141
+ const args = payload.args || [];
142
+ const signalType = 'trace' === payload.level ? 'trace' : 'log';
143
+ return {
144
+ ...base,
145
+ signalType,
146
+ name: payload.message,
147
+ level: payload.level,
148
+ attributes: {
149
+ ...base.attributes || {},
150
+ args
151
+ },
152
+ error: extractError(args)
153
+ };
154
+ }
155
+ if ('timing' === event.type) return {
156
+ ...base,
157
+ signalType: 'metric',
158
+ name: event.payload.name,
159
+ value: event.payload.dur,
160
+ unit: 'ms',
161
+ tags: normalizeLabels(event.payload.tags),
162
+ attributes: {
163
+ ...base.attributes || {},
164
+ desc: event.payload.desc,
165
+ args: event.payload.args
166
+ }
167
+ };
168
+ return {
169
+ ...base,
170
+ signalType: 'metric',
171
+ name: event.payload.name,
172
+ value: 1,
173
+ unit: 'count',
174
+ tags: normalizeLabels(event.payload.tags),
175
+ attributes: {
176
+ ...base.attributes || {},
177
+ args: event.payload.args
178
+ }
179
+ };
180
+ }
181
+ async function postWithTimeout(options) {
182
+ const controller = new AbortController();
183
+ const timer = setTimeout(()=>controller.abort(), options.timeoutMs);
184
+ if ('function' == typeof timer.unref) timer.unref();
185
+ try {
186
+ const response = await fetch(options.endpoint, {
187
+ method: 'POST',
188
+ body: options.body,
189
+ headers: options.headers,
190
+ signal: controller.signal
191
+ });
192
+ if (!response.ok) throw new Error(`Telemetry exporter request failed: ${response.status} ${response.statusText}`);
193
+ } finally{
194
+ clearTimeout(timer);
195
+ }
196
+ }
197
+ function sanitizeMetricName(value) {
198
+ return value.replace(/[^a-zA-Z0-9_:]/g, '_').replace(/_+/g, '_');
199
+ }
200
+ function escapeLabelValue(value) {
201
+ return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
202
+ }
203
+ function toPrometheusLine(envelope, metricPrefix) {
204
+ const metricName = sanitizeMetricName(`${metricPrefix}_${envelope.signalType}_${envelope.name}`);
205
+ const labels = {
206
+ service: envelope.service,
207
+ module: envelope.module,
208
+ environment: envelope.environment,
209
+ ...envelope.level ? {
210
+ level: envelope.level
211
+ } : {},
212
+ ...envelope.traceId ? {
213
+ trace_id: envelope.traceId
214
+ } : {},
215
+ ...envelope.spanId ? {
216
+ span_id: envelope.spanId
217
+ } : {},
218
+ ...envelope.tags || {}
219
+ };
220
+ const labelPairs = Object.entries(labels).sort(([a], [b])=>a.localeCompare(b)).map(([key, value])=>`${sanitizeMetricName(key)}="${escapeLabelValue(value)}"`);
221
+ const labelText = labelPairs.length > 0 ? `{${labelPairs.join(',')}}` : '';
222
+ const value = 'number' == typeof envelope.value && Number.isFinite(envelope.value) ? envelope.value : 1;
223
+ const timestampMs = envelope.timestamp;
224
+ return `${metricName}${labelText} ${value} ${timestampMs}`;
225
+ }
226
+ function createOtlpTelemetryExporter(options = {}) {
227
+ const endpoint = options.endpoint || DEFAULT_OTLP_ENDPOINT;
228
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
229
+ const headers = {
230
+ 'content-type': 'application/json',
231
+ ...options.headers || {}
232
+ };
233
+ return {
234
+ name: 'otlp',
235
+ async emit (batch) {
236
+ if (0 === batch.length) return;
237
+ const body = JSON.stringify({
238
+ resource: {
239
+ service: batch[0]?.service,
240
+ module: batch[0]?.module,
241
+ environment: batch[0]?.environment
242
+ },
243
+ emittedAt: Date.now(),
244
+ events: batch
245
+ });
246
+ await postWithTimeout({
247
+ endpoint,
248
+ body,
249
+ headers,
250
+ timeoutMs
251
+ });
252
+ }
253
+ };
254
+ }
255
+ function createVictoriaMetricsTelemetryExporter(options = {}) {
256
+ const endpoint = options.endpoint || DEFAULT_VM_ENDPOINT;
257
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
258
+ const metricPrefix = sanitizeMetricName(options.metricPrefix || 'modernjs');
259
+ const headers = {
260
+ 'content-type': 'text/plain; version=0.0.4',
261
+ ...options.headers || {}
262
+ };
263
+ return {
264
+ name: 'victoria-metrics',
265
+ async emit (batch) {
266
+ if (0 === batch.length) return;
267
+ const lines = batch.map((item)=>toPrometheusLine(item, metricPrefix));
268
+ await postWithTimeout({
269
+ endpoint,
270
+ body: `${lines.join('\n')}\n`,
271
+ headers,
272
+ timeoutMs
273
+ });
274
+ }
275
+ };
276
+ }
277
+ class TelemetryRegistry {
278
+ async register(exporter) {
279
+ this.exporters.push(exporter);
280
+ this.exporterHealth.set(exporter.name, {
281
+ name: exporter.name,
282
+ healthy: true,
283
+ failures: 0
284
+ });
285
+ if (exporter.init) try {
286
+ await exporter.init({
287
+ service: this.service,
288
+ module: this.module,
289
+ environment: this.environment
290
+ });
291
+ this.markExporterHealthy(exporter.name);
292
+ } catch (error) {
293
+ this.markExporterFailure(exporter.name, error);
294
+ throw error;
295
+ }
296
+ else this.markExporterHealthy(exporter.name);
297
+ }
298
+ getOrCreateExporterHealth(name) {
299
+ const existing = this.exporterHealth.get(name);
300
+ if (existing) return existing;
301
+ const next = {
302
+ name,
303
+ healthy: true,
304
+ failures: 0
305
+ };
306
+ this.exporterHealth.set(name, next);
307
+ return next;
308
+ }
309
+ markExporterHealthy(name) {
310
+ const status = this.getOrCreateExporterHealth(name);
311
+ status.healthy = true;
312
+ status.lastSuccessAt = Date.now();
313
+ status.lastError = void 0;
314
+ }
315
+ markExporterFailure(name, error) {
316
+ const status = this.getOrCreateExporterHealth(name);
317
+ status.healthy = false;
318
+ status.failures += 1;
319
+ status.lastFailureAt = Date.now();
320
+ status.lastError = error instanceof Error ? error.message : String(error);
321
+ }
322
+ maybeEmitSloAlert(type, value, threshold) {
323
+ if (!this.onSloAlert || value < threshold) return;
324
+ const now = Date.now();
325
+ const lastTimestamp = this.lastSloAlertAt.get(type) ?? 0;
326
+ if (now - lastTimestamp < this.alertCooldownMs) return;
327
+ this.lastSloAlertAt.set(type, now);
328
+ const queueDepth = this.queue.length;
329
+ try {
330
+ this.onSloAlert({
331
+ timestamp: now,
332
+ service: this.service,
333
+ module: this.module,
334
+ environment: this.environment,
335
+ type,
336
+ value,
337
+ threshold,
338
+ queueDepth,
339
+ queueCapacity: this.maxQueueSize,
340
+ queueUtilization: queueDepth / this.maxQueueSize,
341
+ totalDropped: this.totalDroppedCount
342
+ });
343
+ } catch (_error) {}
344
+ }
345
+ enqueue(envelope) {
346
+ if (this.samplingRate < 1 && Math.random() > this.samplingRate) return;
347
+ const redactedEnvelope = this.redactionKeys.size > 0 ? {
348
+ ...envelope,
349
+ attributes: redactObject(envelope.attributes, this.redactionKeys)
350
+ } : envelope;
351
+ if (this.queue.length >= this.maxQueueSize) {
352
+ this.queue.shift();
353
+ this.droppedCount += 1;
354
+ this.totalDroppedCount += 1;
355
+ this.maybeEmitSloAlert('queue.drop', this.totalDroppedCount, this.queueDroppedWarnThreshold);
356
+ }
357
+ this.queue.push(redactedEnvelope);
358
+ this.maybeEmitSloAlert('queue.utilization', this.queue.length / this.maxQueueSize, this.queueUtilizationWarnThreshold);
359
+ if (this.queue.length >= this.maxBatchSize) this.flush();
360
+ }
361
+ enqueueMetric(input) {
362
+ this.enqueue({
363
+ timestamp: Date.now(),
364
+ service: this.service,
365
+ module: this.module,
366
+ environment: this.environment,
367
+ signalType: 'metric',
368
+ name: input.name,
369
+ value: input.value,
370
+ unit: input.unit || 'count',
371
+ traceId: input.traceId,
372
+ spanId: input.spanId,
373
+ parentSpanId: input.parentSpanId,
374
+ tags: input.tags,
375
+ attributes: input.attributes
376
+ });
377
+ }
378
+ enqueueLog(input) {
379
+ this.enqueue({
380
+ timestamp: Date.now(),
381
+ service: this.service,
382
+ module: this.module,
383
+ environment: this.environment,
384
+ signalType: 'log',
385
+ name: input.name,
386
+ level: input.level,
387
+ traceId: input.traceId,
388
+ spanId: input.spanId,
389
+ parentSpanId: input.parentSpanId,
390
+ tags: input.tags,
391
+ attributes: input.attributes,
392
+ error: input.error
393
+ });
394
+ }
395
+ enqueueTrace(input) {
396
+ this.enqueue({
397
+ timestamp: Date.now(),
398
+ service: this.service,
399
+ module: this.module,
400
+ environment: this.environment,
401
+ signalType: 'trace',
402
+ name: input.name,
403
+ traceId: input.traceId,
404
+ spanId: input.spanId,
405
+ parentSpanId: input.parentSpanId,
406
+ tags: input.tags,
407
+ attributes: input.attributes
408
+ });
409
+ }
410
+ buildDroppedEnvelope(droppedCount) {
411
+ return {
412
+ timestamp: Date.now(),
413
+ service: this.service,
414
+ module: this.module,
415
+ environment: this.environment,
416
+ signalType: 'metric',
417
+ name: 'telemetry.queue.dropped',
418
+ value: droppedCount,
419
+ unit: 'count',
420
+ tags: {
421
+ reason: 'queue_backpressure'
422
+ }
423
+ };
424
+ }
425
+ buildQueueDepthEnvelope(queueDepth) {
426
+ return {
427
+ timestamp: Date.now(),
428
+ service: this.service,
429
+ module: this.module,
430
+ environment: this.environment,
431
+ signalType: 'metric',
432
+ name: 'telemetry.queue.depth',
433
+ value: queueDepth,
434
+ unit: 'count',
435
+ tags: {
436
+ capacity: String(this.maxQueueSize)
437
+ }
438
+ };
439
+ }
440
+ buildQueueUtilizationEnvelope(queueDepth) {
441
+ return {
442
+ timestamp: Date.now(),
443
+ service: this.service,
444
+ module: this.module,
445
+ environment: this.environment,
446
+ signalType: 'metric',
447
+ name: 'telemetry.queue.utilization',
448
+ value: queueDepth / this.maxQueueSize,
449
+ unit: 'ratio',
450
+ tags: {
451
+ capacity: String(this.maxQueueSize)
452
+ }
453
+ };
454
+ }
455
+ async emitBatch(batch) {
456
+ const results = await Promise.allSettled(this.exporters.map(async (exporter)=>{
457
+ await exporter.emit(batch);
458
+ return exporter.name;
459
+ }));
460
+ for (const [index, result] of results.entries()){
461
+ const exporterName = this.exporters[index]?.name || `exporter-${index}`;
462
+ if ('rejected' === result.status) {
463
+ this.markExporterFailure(exporterName, result.reason);
464
+ continue;
465
+ }
466
+ this.markExporterHealthy(exporterName);
467
+ }
468
+ }
469
+ buildStartupProbeEnvelope() {
470
+ return {
471
+ timestamp: Date.now(),
472
+ service: this.service,
473
+ module: this.module,
474
+ environment: this.environment,
475
+ signalType: 'log',
476
+ name: 'telemetry.exporter.startup_probe',
477
+ level: 'info',
478
+ tags: {
479
+ phase: 'startup'
480
+ },
481
+ attributes: {
482
+ source: 'TelemetryRegistry'
483
+ }
484
+ };
485
+ }
486
+ async startupHealthCheck(options) {
487
+ if (0 === this.exporters.length) return;
488
+ const probeBatch = [
489
+ this.buildStartupProbeEnvelope()
490
+ ];
491
+ const failedExporters = [];
492
+ await Promise.all(this.exporters.map(async (exporter)=>{
493
+ try {
494
+ await exporter.emit(probeBatch);
495
+ this.markExporterHealthy(exporter.name);
496
+ } catch (error) {
497
+ this.markExporterFailure(exporter.name, error);
498
+ const status = this.exporterHealth.get(exporter.name);
499
+ if (status) failedExporters.push({
500
+ ...status
501
+ });
502
+ }
503
+ }));
504
+ if ((options?.failLoud ?? true) && failedExporters.length > 0) throw new TelemetryStartupHealthError(failedExporters);
505
+ }
506
+ getExporterHealth() {
507
+ return Array.from(this.exporterHealth.values()).map((item)=>({
508
+ ...item
509
+ }));
510
+ }
511
+ getQueueStats() {
512
+ return {
513
+ depth: this.queue.length,
514
+ capacity: this.maxQueueSize,
515
+ utilization: this.queue.length / this.maxQueueSize,
516
+ pendingDropped: this.droppedCount,
517
+ totalDropped: this.totalDroppedCount
518
+ };
519
+ }
520
+ async flushInternal() {
521
+ const queueDepthBeforeFlush = this.queue.length;
522
+ if (queueDepthBeforeFlush > 0) {
523
+ this.queue.unshift(this.buildQueueUtilizationEnvelope(queueDepthBeforeFlush));
524
+ this.queue.unshift(this.buildQueueDepthEnvelope(queueDepthBeforeFlush));
525
+ }
526
+ if (this.droppedCount > 0) {
527
+ const droppedCount = this.droppedCount;
528
+ this.droppedCount = 0;
529
+ this.queue.unshift(this.buildDroppedEnvelope(droppedCount));
530
+ }
531
+ if (0 === this.queue.length) return;
532
+ if (0 === this.exporters.length) {
533
+ this.queue.length = 0;
534
+ return;
535
+ }
536
+ while(this.queue.length > 0){
537
+ const batch = this.queue.splice(0, this.maxBatchSize);
538
+ await this.emitBatch(batch);
539
+ }
540
+ await Promise.allSettled(this.exporters.map(async (exporter)=>{
541
+ if (exporter.flush) await exporter.flush();
542
+ }));
543
+ }
544
+ flush() {
545
+ if (this.flushing) return this.flushing;
546
+ this.flushing = this.flushInternal().finally(()=>{
547
+ this.flushing = null;
548
+ });
549
+ return this.flushing;
550
+ }
551
+ async shutdown() {
552
+ if (this.flushTimer) clearInterval(this.flushTimer);
553
+ await this.flush();
554
+ await Promise.allSettled(this.exporters.map(async (exporter)=>{
555
+ if (exporter.shutdown) await exporter.shutdown();
556
+ }));
557
+ }
558
+ constructor(options){
559
+ this.exporters = [];
560
+ this.queue = [];
561
+ this.droppedCount = 0;
562
+ this.totalDroppedCount = 0;
563
+ this.flushing = null;
564
+ this.exporterHealth = new Map();
565
+ this.lastSloAlertAt = new Map();
566
+ this.service = options.service;
567
+ this.module = options.module;
568
+ this.environment = options.environment;
569
+ this.samplingRate = clamp(options.samplingRate ?? 1, 0, 1);
570
+ this.maxBatchSize = Math.max(1, options.maxBatchSize ?? 50);
571
+ this.maxQueueSize = Math.max(1, options.maxQueueSize ?? 1000);
572
+ this.flushIntervalMs = Math.max(50, options.flushIntervalMs ?? 1000);
573
+ this.redactionKeys = new Set(options.redactionKeys || []);
574
+ this.queueUtilizationWarnThreshold = clamp(options.slo?.queueUtilizationWarnThreshold ?? 0.8, 0, 1);
575
+ this.queueDroppedWarnThreshold = Math.max(1, options.slo?.queueDroppedWarnThreshold ?? 1);
576
+ this.alertCooldownMs = Math.max(0, options.slo?.alertCooldownMs ?? 60000);
577
+ this.onSloAlert = options.slo?.onAlert;
578
+ this.flushTimer = setInterval(()=>{
579
+ this.flush();
580
+ }, this.flushIntervalMs);
581
+ if ('function' == typeof this.flushTimer.unref) this.flushTimer.unref();
582
+ }
583
+ }
584
+ class TelemetryCanaryOrchestrator {
585
+ setRequiredContractGates(gates) {
586
+ this.requiredContractGates = Array.from(new Set(gates.map((item)=>item.trim()).filter(Boolean)));
587
+ }
588
+ addRequiredContractGate(name) {
589
+ const normalizedName = name.trim();
590
+ if (!normalizedName) return;
591
+ if (!this.requiredContractGates.includes(normalizedName)) this.requiredContractGates.push(normalizedName);
592
+ }
593
+ setContractGate(name, passed, reason) {
594
+ this.contractGates.set(name, {
595
+ name,
596
+ passed,
597
+ reason,
598
+ updatedAt: Date.now()
599
+ });
600
+ }
601
+ setContractGates(gates) {
602
+ for (const [name, value] of Object.entries(gates)){
603
+ if ('boolean' == typeof value) {
604
+ this.setContractGate(name, value);
605
+ continue;
606
+ }
607
+ this.setContractGate(name, value.passed, value.reason);
608
+ }
609
+ }
610
+ resetToCanary() {
611
+ this.state = 'canary';
612
+ this.consecutiveHealthy = 0;
613
+ this.consecutiveFailures = 0;
614
+ }
615
+ collectFailures() {
616
+ const failures = [];
617
+ const queueStats = this.registry.getQueueStats();
618
+ const unhealthyExporterCount = this.registry.getExporterHealth().filter((item)=>!item.healthy).length;
619
+ if (queueStats.utilization > this.maxQueueUtilization) failures.push({
620
+ reason: 'queue_utilization',
621
+ threshold: this.maxQueueUtilization,
622
+ value: queueStats.utilization
623
+ });
624
+ if (queueStats.totalDropped > this.maxTotalDropped) failures.push({
625
+ reason: 'queue_dropped',
626
+ threshold: this.maxTotalDropped,
627
+ value: queueStats.totalDropped
628
+ });
629
+ if (unhealthyExporterCount > this.maxUnhealthyExporters) failures.push({
630
+ reason: 'unhealthy_exporter',
631
+ threshold: this.maxUnhealthyExporters,
632
+ value: unhealthyExporterCount
633
+ });
634
+ for (const gateName of this.requiredContractGates){
635
+ const gate = this.contractGates.get(gateName);
636
+ if (!gate) {
637
+ failures.push({
638
+ reason: 'contract_gate_missing',
639
+ gate: gateName,
640
+ message: `Contract gate "${gateName}" is missing`
641
+ });
642
+ continue;
643
+ }
644
+ if (!gate.passed) failures.push({
645
+ reason: 'contract_gate_failed',
646
+ gate: gateName,
647
+ message: gate.reason || `Contract gate "${gateName}" is not passing`
648
+ });
649
+ }
650
+ return {
651
+ failures,
652
+ queueStats,
653
+ unhealthyExporterCount
654
+ };
655
+ }
656
+ evaluate() {
657
+ const now = Date.now();
658
+ const { failures, queueStats, unhealthyExporterCount } = this.collectFailures();
659
+ let action = 'hold';
660
+ if (failures.length > 0) {
661
+ this.consecutiveHealthy = 0;
662
+ this.consecutiveFailures += 1;
663
+ if ('rolled_back' !== this.state && this.consecutiveFailures >= this.rollbackConsecutiveFailures) {
664
+ this.state = 'rolled_back';
665
+ action = 'rollback';
666
+ }
667
+ } else {
668
+ this.consecutiveFailures = 0;
669
+ this.consecutiveHealthy += 1;
670
+ if ('canary' === this.state && this.consecutiveHealthy >= this.minConsecutiveHealthyEvaluations) {
671
+ this.state = 'promoted';
672
+ action = 'promote';
673
+ }
674
+ }
675
+ const decision = {
676
+ timestamp: now,
677
+ action,
678
+ state: this.state,
679
+ consecutiveHealthy: this.consecutiveHealthy,
680
+ consecutiveFailures: this.consecutiveFailures,
681
+ failures,
682
+ queueStats,
683
+ unhealthyExporterCount,
684
+ contractGates: Array.from(this.contractGates.values()).map((item)=>({
685
+ ...item
686
+ }))
687
+ };
688
+ try {
689
+ this.onEvaluate?.(decision);
690
+ } catch (_error) {}
691
+ if ('promote' === action) try {
692
+ this.onPromote?.(decision);
693
+ } catch (_error) {}
694
+ if ('rollback' === action) try {
695
+ this.onRollback?.(decision);
696
+ } catch (_error) {}
697
+ return decision;
698
+ }
699
+ getStatusSnapshot() {
700
+ const now = Date.now();
701
+ const { failures, queueStats, unhealthyExporterCount } = this.collectFailures();
702
+ return {
703
+ timestamp: now,
704
+ state: this.state,
705
+ consecutiveHealthy: this.consecutiveHealthy,
706
+ consecutiveFailures: this.consecutiveFailures,
707
+ queueStats,
708
+ unhealthyExporterCount,
709
+ requiredContractGates: [
710
+ ...this.requiredContractGates
711
+ ],
712
+ contractGates: Array.from(this.contractGates.values()).map((item)=>({
713
+ ...item
714
+ })),
715
+ failurePreview: failures
716
+ };
717
+ }
718
+ start() {
719
+ if (this.evaluationTimer) return;
720
+ this.evaluationTimer = setInterval(()=>{
721
+ this.evaluate();
722
+ }, this.evaluationIntervalMs);
723
+ if ('function' == typeof this.evaluationTimer.unref) this.evaluationTimer.unref();
724
+ }
725
+ stop() {
726
+ if (this.evaluationTimer) {
727
+ clearInterval(this.evaluationTimer);
728
+ this.evaluationTimer = void 0;
729
+ }
730
+ }
731
+ constructor(options){
732
+ this.requiredContractGates = [];
733
+ this.contractGates = new Map();
734
+ this.state = 'canary';
735
+ this.consecutiveHealthy = 0;
736
+ this.consecutiveFailures = 0;
737
+ this.registry = options.registry;
738
+ this.evaluationIntervalMs = Math.max(250, options.evaluationIntervalMs ?? 15000);
739
+ this.minConsecutiveHealthyEvaluations = Math.max(1, options.minConsecutiveHealthyEvaluations ?? 3);
740
+ this.rollbackConsecutiveFailures = Math.max(1, options.rollbackConsecutiveFailures ?? 2);
741
+ this.maxQueueUtilization = clamp(options.maxQueueUtilization ?? 0.8, 0, 1);
742
+ this.maxTotalDropped = Math.max(0, options.maxTotalDropped ?? 0);
743
+ this.maxUnhealthyExporters = Math.max(0, options.maxUnhealthyExporters ?? 0);
744
+ this.setRequiredContractGates(options.requiredContractGates || []);
745
+ this.onEvaluate = options.onEvaluate;
746
+ this.onPromote = options.onPromote;
747
+ this.onRollback = options.onRollback;
748
+ }
749
+ }
750
+ function normalizeMetricsInput(prefixOrTags, tags) {
751
+ if ('string' == typeof prefixOrTags) return {
752
+ prefix: prefixOrTags,
753
+ tags: tags || {}
754
+ };
755
+ if (isRecord(prefixOrTags)) return {
756
+ prefix: void 0,
757
+ tags: prefixOrTags
758
+ };
759
+ return {
760
+ prefix: void 0,
761
+ tags: tags || {}
762
+ };
763
+ }
764
+ function normalizeMetricName(name, prefix) {
765
+ return prefix && prefix.length > 0 ? `${prefix}.${name}` : name;
766
+ }
767
+ function toTelemetryMetricTags(tags) {
768
+ const output = {};
769
+ for (const [key, value] of Object.entries(tags))if (null != value) output[key] = String(value);
770
+ return output;
771
+ }
772
+ function getTraceContext(tags) {
773
+ const traceId = 'string' == typeof tags.trace_id ? tags.trace_id : 'string' == typeof tags.traceId ? tags.traceId : void 0;
774
+ const spanId = 'string' == typeof tags.span_id ? tags.span_id : 'string' == typeof tags.spanId ? tags.spanId : void 0;
775
+ const parentSpanId = 'string' == typeof tags.parent_span_id ? tags.parent_span_id : 'string' == typeof tags.parentSpanId ? tags.parentSpanId : void 0;
776
+ return {
777
+ traceId,
778
+ spanId,
779
+ parentSpanId
780
+ };
781
+ }
782
+ const createTelemetryAwareMetrics = (baseMetrics, registry)=>{
783
+ const emitCounter = (name, value, prefixOrTags, tags)=>{
784
+ const normalized = normalizeMetricsInput(prefixOrTags, tags);
785
+ baseMetrics.emitCounter(name, value, normalized.prefix, normalized.tags);
786
+ try {
787
+ const metricName = normalizeMetricName(name, normalized.prefix);
788
+ const traceContext = getTraceContext(normalized.tags);
789
+ registry.enqueueMetric({
790
+ name: metricName,
791
+ value,
792
+ unit: 'count',
793
+ traceId: traceContext.traceId,
794
+ spanId: traceContext.spanId,
795
+ parentSpanId: traceContext.parentSpanId,
796
+ tags: toTelemetryMetricTags(normalized.tags),
797
+ attributes: normalized.tags
798
+ });
799
+ } catch (_error) {}
800
+ };
801
+ const emitTimer = (name, value, prefixOrTags, tags)=>{
802
+ const normalized = normalizeMetricsInput(prefixOrTags, tags);
803
+ baseMetrics.emitTimer(name, value, normalized.prefix, normalized.tags);
804
+ try {
805
+ const metricName = normalizeMetricName(name, normalized.prefix);
806
+ const traceContext = getTraceContext(normalized.tags);
807
+ registry.enqueueMetric({
808
+ name: metricName,
809
+ value,
810
+ unit: 'ms',
811
+ traceId: traceContext.traceId,
812
+ spanId: traceContext.spanId,
813
+ parentSpanId: traceContext.parentSpanId,
814
+ tags: toTelemetryMetricTags(normalized.tags),
815
+ attributes: normalized.tags
816
+ });
817
+ } catch (_error) {}
818
+ };
819
+ return {
820
+ ...baseMetrics,
821
+ emitCounter,
822
+ emitTimer
823
+ };
824
+ };
825
+ function resolveRuntimeFallbackSignalEndpoint(configuredEndpoint) {
826
+ const rawEndpoint = configuredEndpoint?.trim();
827
+ if (!rawEndpoint) return DEFAULT_RUNTIME_FALLBACK_SIGNAL_ENDPOINT;
828
+ if (rawEndpoint.startsWith('/')) return rawEndpoint;
829
+ try {
830
+ return new URL(rawEndpoint).pathname || DEFAULT_RUNTIME_FALLBACK_SIGNAL_ENDPOINT;
831
+ } catch (_error) {
832
+ return `/${rawEndpoint.replace(/^\/+/, '')}`;
833
+ }
834
+ }
835
+ function createRuntimeSignalError(message, code) {
836
+ const error = new Error(message);
837
+ error.code = code;
838
+ return error;
839
+ }
840
+ function getUtf8ByteLength(input) {
841
+ if ("u" > typeof Buffer) return Buffer.byteLength(input);
842
+ return new TextEncoder().encode(input).length;
843
+ }
844
+ function normalizeRuntimeSignalOrigin(value) {
845
+ if ('string' != typeof value || 0 === value.trim().length) return;
846
+ try {
847
+ return new URL(value).origin;
848
+ } catch (_error) {
849
+ return;
850
+ }
851
+ }
852
+ function normalizeRuntimeSignalAppName(payload) {
853
+ if ('string' != typeof payload.appName) return 'unknown';
854
+ const normalized = payload.appName.trim();
855
+ return normalized.length > 0 ? normalized : 'unknown';
856
+ }
857
+ function normalizeRuntimeSignalRuntimeDigest(payload) {
858
+ if ('string' == typeof payload.runtimeDigest && payload.runtimeDigest.trim()) return payload.runtimeDigest.trim();
859
+ const metadata = payload.metadata;
860
+ if (metadata && 'object' == typeof metadata && !Array.isArray(metadata) && 'string' == typeof metadata.runtimeDigest) {
861
+ const digest = String(metadata.runtimeDigest).trim();
862
+ if (digest) return digest;
863
+ }
864
+ }
865
+ function normalizeRuntimeFallbackSignalAuthConfig(configured) {
866
+ const headerName = 'string' == typeof configured?.headerName && configured.headerName.trim() ? configured.headerName.trim().toLowerCase() : DEFAULT_RUNTIME_FALLBACK_AUTH_HEADER;
867
+ const expectedFromEnv = 'string' == typeof configured?.expectedValueEnv && configured.expectedValueEnv.trim().length > 0 ? process.env[configured.expectedValueEnv.trim()] : void 0;
868
+ const expectedFromConfig = 'string' == typeof configured?.expectedValue && configured.expectedValue.trim().length > 0 ? configured.expectedValue.trim() : void 0;
869
+ const expectedValue = expectedFromConfig || expectedFromEnv;
870
+ const enabled = configured?.enabled === true;
871
+ if (enabled && !expectedValue) throw new Error('[telemetry.canary.autopilot.runtimeFallbackSignal] auth.enabled is true but no expected token is configured');
872
+ return {
873
+ enabled,
874
+ headerName,
875
+ expectedValue
876
+ };
877
+ }
878
+ function enforceRuntimeFallbackSignalAuthToken(token, authConfig) {
879
+ if (!authConfig.enabled) return;
880
+ if (!token || token !== authConfig.expectedValue) throw createRuntimeSignalError('runtime fallback signal auth failed', 'UNAUTHORIZED');
881
+ }
882
+ function enforceRuntimeFallbackSignalAuth(c, runtimeSignalConfig) {
883
+ enforceRuntimeFallbackSignalAuthToken(c.req.header(runtimeSignalConfig.auth.headerName), runtimeSignalConfig.auth);
884
+ }
885
+ function normalizeRuntimeFallbackTrustPolicy(configured) {
886
+ const allowedApps = Array.isArray(configured?.allowedApps) ? configured.allowedApps.map((item)=>'string' == typeof item ? item.trim() : '').filter(Boolean) : [];
887
+ const allowedEntryOrigins = Array.isArray(configured?.allowedEntryOrigins) ? configured.allowedEntryOrigins.map((item)=>normalizeRuntimeSignalOrigin(item)).filter((item)=>Boolean(item)) : [];
888
+ const expectedRuntimeDigestsRaw = configured?.expectedRuntimeDigests || {};
889
+ const expectedRuntimeDigests = {};
890
+ Object.entries(expectedRuntimeDigestsRaw).forEach(([appName, digest])=>{
891
+ if ('string' == typeof appName && appName.trim().length > 0 && 'string' == typeof digest && digest.trim().length > 0) expectedRuntimeDigests[appName.trim()] = digest.trim();
892
+ });
893
+ return {
894
+ allowedApps,
895
+ allowedEntryOrigins,
896
+ expectedRuntimeDigests,
897
+ enforceRuntimeDigest: configured?.enforceRuntimeDigest === true,
898
+ maxSignalsPerWindow: Math.max(1, Math.floor(configured?.maxSignalsPerWindow ?? DEFAULT_RUNTIME_FALLBACK_TRUST_MAX_SIGNALS_PER_WINDOW)),
899
+ windowMs: Math.max(1000, Math.floor(configured?.windowMs ?? DEFAULT_RUNTIME_FALLBACK_TRUST_WINDOW_MS)),
900
+ dedupeWindowMs: Math.max(0, Math.floor(configured?.dedupeWindowMs ?? DEFAULT_RUNTIME_FALLBACK_TRUST_DEDUPE_WINDOW_MS))
901
+ };
902
+ }
903
+ function createRuntimeFallbackSignalRuntimeState() {
904
+ return {
905
+ rateLimitBySource: new Map(),
906
+ dedupeByFingerprint: new Map()
907
+ };
908
+ }
909
+ function cleanupRuntimeFallbackSignalRuntimeState(now, runtimeState, trustPolicy) {
910
+ const dedupeExpiryMs = Math.max(trustPolicy.dedupeWindowMs, trustPolicy.windowMs, 1000);
911
+ runtimeState.dedupeByFingerprint.forEach((lastSeenAt, fingerprint)=>{
912
+ if (now - lastSeenAt > dedupeExpiryMs) runtimeState.dedupeByFingerprint.delete(fingerprint);
913
+ });
914
+ runtimeState.rateLimitBySource.forEach((state, source)=>{
915
+ if (now - state.windowStartedAt > 2 * trustPolicy.windowMs) runtimeState.rateLimitBySource.delete(source);
916
+ });
917
+ }
918
+ function enforceRuntimeFallbackSignalTrustPolicy(payload, runtimeSignalContext) {
919
+ const { trustPolicy, runtimeState } = runtimeSignalContext;
920
+ const now = Date.now();
921
+ cleanupRuntimeFallbackSignalRuntimeState(now, runtimeState, trustPolicy);
922
+ const appName = normalizeRuntimeSignalAppName(payload);
923
+ const entryOrigin = normalizeRuntimeSignalOrigin(payload.entry);
924
+ const runtimeDigest = normalizeRuntimeSignalRuntimeDigest(payload);
925
+ if (trustPolicy.allowedApps.length > 0 && !trustPolicy.allowedApps.includes(appName)) throw createRuntimeSignalError(`runtime fallback signal app "${appName}" is not trusted`, 'UNTRUSTED_SOURCE');
926
+ if (trustPolicy.allowedEntryOrigins.length > 0) {
927
+ if (!entryOrigin || !trustPolicy.allowedEntryOrigins.includes(entryOrigin)) throw createRuntimeSignalError(`runtime fallback signal entry origin "${entryOrigin || 'unknown'}" is not trusted`, 'UNTRUSTED_SOURCE');
928
+ }
929
+ const expectedDigest = trustPolicy.expectedRuntimeDigests[appName];
930
+ if (expectedDigest && runtimeDigest !== expectedDigest) throw createRuntimeSignalError(`runtime fallback runtimeDigest mismatch for app "${appName}"`, 'UNTRUSTED_SOURCE');
931
+ if (trustPolicy.enforceRuntimeDigest && !runtimeDigest) throw createRuntimeSignalError(`runtime fallback signal for app "${appName}" is missing runtimeDigest`, 'UNTRUSTED_SOURCE');
932
+ const dedupeFingerprint = JSON.stringify({
933
+ appName,
934
+ entryOrigin: entryOrigin || 'unknown',
935
+ reason: payload.reason || 'runtime_fallback',
936
+ phase: payload.phase || 'unknown',
937
+ runtimeDigest: runtimeDigest || 'unknown'
938
+ });
939
+ const dedupeWindowMs = trustPolicy.dedupeWindowMs;
940
+ if (dedupeWindowMs > 0) {
941
+ const lastSeenAt = runtimeState.dedupeByFingerprint.get(dedupeFingerprint);
942
+ runtimeState.dedupeByFingerprint.set(dedupeFingerprint, now);
943
+ if ('number' == typeof lastSeenAt && now - lastSeenAt <= dedupeWindowMs) return {
944
+ deduped: true
945
+ };
946
+ } else runtimeState.dedupeByFingerprint.set(dedupeFingerprint, now);
947
+ const sourceKey = `${appName}@${entryOrigin || 'unknown'}`;
948
+ const rateState = runtimeState.rateLimitBySource.get(sourceKey);
949
+ if (!rateState || now - rateState.windowStartedAt > trustPolicy.windowMs) runtimeState.rateLimitBySource.set(sourceKey, {
950
+ count: 1,
951
+ windowStartedAt: now
952
+ });
953
+ else {
954
+ if (rateState.count >= trustPolicy.maxSignalsPerWindow) throw createRuntimeSignalError(`runtime fallback signal rate-limited for source "${sourceKey}"`, 'RATE_LIMITED');
955
+ rateState.count += 1;
956
+ }
957
+ return {
958
+ deduped: false
959
+ };
960
+ }
961
+ function maybeWarnLegacyOtlpEndpoint(endpoint) {
962
+ if (!endpoint || !endpoint.includes('/v1/metrics')) return;
963
+ console.warn(`[telemetry] OTLP endpoint "${endpoint}" looks like a metrics path. UltraModern telemetry exporter expects log-style envelopes (default: ${DEFAULT_OTLP_ENDPOINT}).`);
964
+ }
965
+ async function parseRuntimeFallbackSignalPayload(c, maxBodyBytes) {
966
+ const contentLengthHeader = c.req.header('content-length');
967
+ if (contentLengthHeader) {
968
+ const contentLength = Number.parseInt(contentLengthHeader, 10);
969
+ if (Number.isFinite(contentLength) && contentLength > maxBodyBytes) throw createRuntimeSignalError('runtime fallback signal payload too large', 'PAYLOAD_TOO_LARGE');
970
+ }
971
+ const rawBody = await c.req.raw.text();
972
+ const payload = parseRuntimeFallbackSignalPayloadFromRawBody(rawBody, maxBodyBytes);
973
+ return {
974
+ rawBody,
975
+ payload
976
+ };
977
+ }
978
+ function parseRuntimeFallbackSignalPayloadFromRawBody(rawBody, maxBodyBytes) {
979
+ if (!rawBody || 0 === rawBody.trim().length) throw createRuntimeSignalError('runtime fallback signal body is empty', 'INVALID_PAYLOAD');
980
+ if (getUtf8ByteLength(rawBody) > maxBodyBytes) throw createRuntimeSignalError('runtime fallback signal payload too large', 'PAYLOAD_TOO_LARGE');
981
+ let payload;
982
+ try {
983
+ payload = JSON.parse(rawBody);
984
+ } catch (_error) {
985
+ throw createRuntimeSignalError('runtime fallback signal body must be valid JSON', 'INVALID_PAYLOAD');
986
+ }
987
+ if (!payload || 'object' != typeof payload || Array.isArray(payload)) throw createRuntimeSignalError('runtime fallback signal body must be a JSON object', 'INVALID_PAYLOAD');
988
+ return payload;
989
+ }
990
+ function getRuntimeSignalErrorStatusCode(signalError) {
991
+ if ('PAYLOAD_TOO_LARGE' === signalError.code) return 413;
992
+ if ('INVALID_PAYLOAD' === signalError.code) return 400;
993
+ if ('UNAUTHORIZED' === signalError.code) return 401;
994
+ if ('RATE_LIMITED' === signalError.code) return 429;
995
+ if ('UNTRUSTED_SOURCE' === signalError.code) return 403;
996
+ return 500;
997
+ }
998
+ async function persistRuntimeFallbackContractGate(payload, runtimeSignalConfig) {
999
+ const now = Date.now();
1000
+ const gateSnapshotStore = await runtimeSignalConfig.gateSnapshotStore;
1001
+ const snapshot = await gateSnapshotStore.readSnapshot() || {};
1002
+ const existingGates = snapshot.gates && 'object' == typeof snapshot.gates ? snapshot.gates : {};
1003
+ const reason = 'string' == typeof payload.reason ? payload.reason : 'runtime_fallback';
1004
+ const phase = 'string' == typeof payload.phase ? payload.phase : 'unknown';
1005
+ const appName = 'string' == typeof payload.appName ? payload.appName : 'unknown';
1006
+ const entry = 'string' == typeof payload.entry ? payload.entry : void 0;
1007
+ snapshot.schemaVersion = 'number' == typeof snapshot.schemaVersion ? snapshot.schemaVersion : external_contractGateSnapshotStore_js_namespaceObject.CONTRACT_GATE_SNAPSHOT_SCHEMA_VERSION;
1008
+ snapshot.updatedAt = now;
1009
+ snapshot.gates = {
1010
+ ...existingGates,
1011
+ [runtimeSignalConfig.gateName]: {
1012
+ passed: false,
1013
+ reason: `runtime_fallback:${reason} phase=${phase} app=${appName}${entry ? ` entry=${entry}` : ''}`,
1014
+ updatedAt: now,
1015
+ expiresAt: now + runtimeSignalConfig.failureHoldMs,
1016
+ source: 'runtime-mf-fallback-signal',
1017
+ metadata: payload
1018
+ }
1019
+ };
1020
+ await gateSnapshotStore.writeSnapshot(snapshot);
1021
+ }
1022
+ function emitCanaryDecisionMetric(registry, decision, action) {
1023
+ try {
1024
+ registry.enqueueMetric({
1025
+ name: `telemetry.canary.${action}`,
1026
+ value: 1,
1027
+ unit: 'count',
1028
+ tags: {
1029
+ action,
1030
+ state: decision.state,
1031
+ failures: String(decision.failures.length)
1032
+ }
1033
+ });
1034
+ } catch (_error) {}
1035
+ }
1036
+ const hasEnabledTelemetryExporters = (config)=>Boolean(config?.exporters?.otlp?.enabled || config?.exporters?.victoriaMetrics?.enabled);
1037
+ const injectTelemetryPlugin = ()=>({
1038
+ name: '@modern-js/inject-telemetry',
1039
+ setup (api) {
1040
+ const serverConfig = api.getServerConfig();
1041
+ const telemetryConfig = serverConfig?.server?.telemetry;
1042
+ if (!telemetryConfig) return;
1043
+ if (true !== telemetryConfig.enabled && !hasEnabledTelemetryExporters(telemetryConfig)) return;
1044
+ const { middlewares, metaName, appDirectory } = api.getServerContext();
1045
+ const serviceName = telemetryConfig.service || metaName || 'modern-js';
1046
+ const moduleName = telemetryConfig.module || 'server';
1047
+ const environmentName = telemetryConfig.environment || process.env.MODERN_ENV || process.env.NODE_ENV || 'development';
1048
+ const registry = new TelemetryRegistry({
1049
+ service: serviceName,
1050
+ module: moduleName,
1051
+ environment: environmentName,
1052
+ samplingRate: telemetryConfig.samplingRate,
1053
+ flushIntervalMs: telemetryConfig.flushIntervalMs,
1054
+ maxBatchSize: telemetryConfig.maxBatchSize,
1055
+ maxQueueSize: telemetryConfig.maxQueueSize,
1056
+ redactionKeys: telemetryConfig.redactionKeys
1057
+ });
1058
+ let canaryOrchestrator;
1059
+ let contractGateAutopilot;
1060
+ let runtimeFallbackSignalConfig;
1061
+ let gateSnapshotStorePromise;
1062
+ const canaryConfig = telemetryConfig.canary;
1063
+ if (canaryConfig?.enabled) {
1064
+ const contractGates = canaryConfig.contractGates;
1065
+ canaryOrchestrator = new TelemetryCanaryOrchestrator({
1066
+ registry,
1067
+ evaluationIntervalMs: canaryConfig.evaluationIntervalMs,
1068
+ minConsecutiveHealthyEvaluations: canaryConfig.minConsecutiveHealthyEvaluations,
1069
+ rollbackConsecutiveFailures: canaryConfig.rollbackConsecutiveFailures,
1070
+ maxQueueUtilization: canaryConfig.maxQueueUtilization,
1071
+ maxTotalDropped: canaryConfig.maxTotalDropped,
1072
+ maxUnhealthyExporters: canaryConfig.maxUnhealthyExporters,
1073
+ requiredContractGates: Object.keys(contractGates || {}),
1074
+ onPromote: (decision)=>{
1075
+ emitCanaryDecisionMetric(registry, decision, 'promote');
1076
+ },
1077
+ onRollback: (decision)=>{
1078
+ emitCanaryDecisionMetric(registry, decision, 'rollback');
1079
+ }
1080
+ });
1081
+ if (contractGates) canaryOrchestrator.setContractGates(contractGates);
1082
+ const autopilotEnabled = canaryConfig.autopilot?.enabled ?? true;
1083
+ if (autopilotEnabled) {
1084
+ const gateSnapshotPath = (0, external_contractGateSnapshotStore_js_namespaceObject.resolveContractGateSnapshotPath)(appDirectory, canaryConfig.autopilot?.gateSnapshotPath);
1085
+ gateSnapshotStorePromise = (0, external_contractGateSnapshotStore_js_namespaceObject.resolveContractGateSnapshotStore)({
1086
+ appDirectory,
1087
+ gateSnapshotPath: gateSnapshotPath || external_contractGateSnapshotStore_js_namespaceObject.DEFAULT_CONTRACT_GATE_SNAPSHOT_PATH,
1088
+ stateStore: canaryConfig.autopilot?.stateStore
1089
+ });
1090
+ const runtimeSignalConfig = canaryConfig.autopilot?.runtimeFallbackSignal;
1091
+ const runtimeSignalEnabled = runtimeSignalConfig?.enabled ?? true;
1092
+ if (runtimeSignalEnabled && gateSnapshotStorePromise) runtimeFallbackSignalConfig = {
1093
+ endpoint: resolveRuntimeFallbackSignalEndpoint(runtimeSignalConfig?.endpoint),
1094
+ gateName: runtimeSignalConfig?.gateName?.trim() || DEFAULT_RUNTIME_FALLBACK_GATE_NAME,
1095
+ gateSnapshotStore: gateSnapshotStorePromise,
1096
+ failureHoldMs: Math.max(1000, runtimeSignalConfig?.failureHoldMs ?? DEFAULT_RUNTIME_FALLBACK_FAILURE_HOLD_MS),
1097
+ maxBodyBytes: Math.max(512, runtimeSignalConfig?.maxBodyBytes ?? DEFAULT_RUNTIME_FALLBACK_MAX_BODY_BYTES),
1098
+ auth: normalizeRuntimeFallbackSignalAuthConfig(runtimeSignalConfig?.auth),
1099
+ trustPolicy: normalizeRuntimeFallbackTrustPolicy(runtimeSignalConfig?.trustPolicy),
1100
+ runtimeState: createRuntimeFallbackSignalRuntimeState()
1101
+ };
1102
+ }
1103
+ }
1104
+ if (runtimeFallbackSignalConfig) {
1105
+ const signalConfig = runtimeFallbackSignalConfig;
1106
+ middlewares.push({
1107
+ name: 'telemetry-runtime-fallback-signal',
1108
+ path: signalConfig.endpoint,
1109
+ method: 'post',
1110
+ order: 'pre',
1111
+ handler: async (c)=>{
1112
+ try {
1113
+ enforceRuntimeFallbackSignalAuth(c, signalConfig);
1114
+ const { payload } = await parseRuntimeFallbackSignalPayload(c, signalConfig.maxBodyBytes);
1115
+ const trustResult = enforceRuntimeFallbackSignalTrustPolicy(payload, signalConfig);
1116
+ if (trustResult.deduped) return c.json({
1117
+ ok: true,
1118
+ deduped: true
1119
+ }, 202);
1120
+ await persistRuntimeFallbackContractGate(payload, signalConfig);
1121
+ return c.json({
1122
+ ok: true
1123
+ }, 202);
1124
+ } catch (error) {
1125
+ const signalError = error;
1126
+ const status = getRuntimeSignalErrorStatusCode(signalError);
1127
+ return c.json({
1128
+ ok: false,
1129
+ error: signalError instanceof Error ? signalError.message : String(signalError)
1130
+ }, status);
1131
+ }
1132
+ }
1133
+ });
1134
+ }
1135
+ middlewares.push({
1136
+ name: 'telemetry-runtime-status',
1137
+ path: DEFAULT_RUNTIME_STATUS_ENDPOINT,
1138
+ method: 'get',
1139
+ order: 'pre',
1140
+ handler: async (c)=>{
1141
+ try {
1142
+ if (runtimeFallbackSignalConfig?.auth.enabled) enforceRuntimeFallbackSignalAuthToken(c.req.header(runtimeFallbackSignalConfig.auth.headerName), runtimeFallbackSignalConfig.auth);
1143
+ return c.json({
1144
+ ok: true,
1145
+ timestamp: Date.now(),
1146
+ telemetry: {
1147
+ queueStats: registry.getQueueStats(),
1148
+ exporterHealth: registry.getExporterHealth()
1149
+ },
1150
+ canary: canaryOrchestrator ? {
1151
+ enabled: true,
1152
+ ...canaryOrchestrator.getStatusSnapshot()
1153
+ } : {
1154
+ enabled: false
1155
+ },
1156
+ runtimeFallbackSignal: runtimeFallbackSignalConfig ? {
1157
+ enabled: true,
1158
+ endpoint: runtimeFallbackSignalConfig.endpoint,
1159
+ gateName: runtimeFallbackSignalConfig.gateName,
1160
+ failureHoldMs: runtimeFallbackSignalConfig.failureHoldMs,
1161
+ maxBodyBytes: runtimeFallbackSignalConfig.maxBodyBytes,
1162
+ auth: {
1163
+ enabled: runtimeFallbackSignalConfig.auth.enabled,
1164
+ headerName: runtimeFallbackSignalConfig.auth.headerName
1165
+ },
1166
+ trustPolicy: {
1167
+ allowedApps: runtimeFallbackSignalConfig.trustPolicy.allowedApps,
1168
+ allowedEntryOrigins: runtimeFallbackSignalConfig.trustPolicy.allowedEntryOrigins,
1169
+ enforceRuntimeDigest: runtimeFallbackSignalConfig.trustPolicy.enforceRuntimeDigest,
1170
+ expectedRuntimeDigestsCount: Object.keys(runtimeFallbackSignalConfig.trustPolicy.expectedRuntimeDigests).length,
1171
+ maxSignalsPerWindow: runtimeFallbackSignalConfig.trustPolicy.maxSignalsPerWindow,
1172
+ windowMs: runtimeFallbackSignalConfig.trustPolicy.windowMs,
1173
+ dedupeWindowMs: runtimeFallbackSignalConfig.trustPolicy.dedupeWindowMs
1174
+ }
1175
+ } : {
1176
+ enabled: false
1177
+ }
1178
+ });
1179
+ } catch (error) {
1180
+ const signalError = error;
1181
+ return c.json({
1182
+ ok: false,
1183
+ error: signalError instanceof Error ? signalError.message : String(signalError)
1184
+ }, getRuntimeSignalErrorStatusCode(signalError));
1185
+ }
1186
+ }
1187
+ });
1188
+ middlewares.push({
1189
+ name: 'inject-telemetry',
1190
+ handler: async (c, next)=>{
1191
+ const monitors = c.get('monitors');
1192
+ if (monitors) {
1193
+ const traceContext = parseTraceparent(c.req.header('traceparent'));
1194
+ const monitor = (event)=>{
1195
+ registry.enqueue(toTelemetryEnvelope(event, {
1196
+ service: serviceName,
1197
+ module: moduleName,
1198
+ environment: environmentName,
1199
+ traceId: traceContext?.traceId,
1200
+ spanId: traceContext?.spanId,
1201
+ attributes: {
1202
+ requestMethod: c.req.method,
1203
+ requestPath: c.req.path
1204
+ }
1205
+ }));
1206
+ };
1207
+ monitors.push(monitor);
1208
+ }
1209
+ await next();
1210
+ }
1211
+ });
1212
+ let prepared = false;
1213
+ api.onPrepare(async ()=>{
1214
+ if (prepared) return;
1215
+ prepared = true;
1216
+ if (telemetryConfig.exporters?.otlp?.enabled) {
1217
+ maybeWarnLegacyOtlpEndpoint(telemetryConfig.exporters.otlp.endpoint);
1218
+ await registry.register(createOtlpTelemetryExporter(telemetryConfig.exporters.otlp));
1219
+ }
1220
+ if (telemetryConfig.exporters?.victoriaMetrics?.enabled) await registry.register(createVictoriaMetricsTelemetryExporter(telemetryConfig.exporters.victoriaMetrics));
1221
+ await registry.startupHealthCheck({
1222
+ failLoud: telemetryConfig.failLoudStartup ?? true
1223
+ });
1224
+ if (!canaryOrchestrator) return;
1225
+ canaryOrchestrator.start();
1226
+ if (gateSnapshotStorePromise) {
1227
+ const gateSnapshotStore = await gateSnapshotStorePromise;
1228
+ contractGateAutopilot = new external_contractGateAutopilot_js_namespaceObject.ContractGateAutopilot({
1229
+ orchestrator: canaryOrchestrator,
1230
+ gateSnapshotPath: (0, external_contractGateSnapshotStore_js_namespaceObject.resolveContractGateSnapshotPath)(appDirectory, canaryConfig?.autopilot?.gateSnapshotPath),
1231
+ gateSnapshotStore,
1232
+ pollIntervalMs: canaryConfig?.autopilot?.pollIntervalMs,
1233
+ gateStaleAfterMs: canaryConfig?.autopilot?.gateStaleAfterMs
1234
+ });
1235
+ }
1236
+ if (contractGateAutopilot) await contractGateAutopilot.start();
1237
+ canaryOrchestrator.evaluate();
1238
+ });
1239
+ }
1240
+ });
1241
+ exports.DEFAULT_RUNTIME_FALLBACK_SIGNAL_ENDPOINT = __webpack_exports__.DEFAULT_RUNTIME_FALLBACK_SIGNAL_ENDPOINT;
1242
+ exports.DEFAULT_RUNTIME_STATUS_ENDPOINT = __webpack_exports__.DEFAULT_RUNTIME_STATUS_ENDPOINT;
1243
+ exports.TelemetryCanaryOrchestrator = __webpack_exports__.TelemetryCanaryOrchestrator;
1244
+ exports.TelemetryRegistry = __webpack_exports__.TelemetryRegistry;
1245
+ exports.TelemetryStartupHealthError = __webpack_exports__.TelemetryStartupHealthError;
1246
+ exports.createOtlpTelemetryExporter = __webpack_exports__.createOtlpTelemetryExporter;
1247
+ exports.createRuntimeFallbackSignalRuntimeState = __webpack_exports__.createRuntimeFallbackSignalRuntimeState;
1248
+ exports.createRuntimeSignalError = __webpack_exports__.createRuntimeSignalError;
1249
+ exports.createTelemetryAwareMetrics = __webpack_exports__.createTelemetryAwareMetrics;
1250
+ exports.createVictoriaMetricsTelemetryExporter = __webpack_exports__.createVictoriaMetricsTelemetryExporter;
1251
+ exports.enforceRuntimeFallbackSignalAuthToken = __webpack_exports__.enforceRuntimeFallbackSignalAuthToken;
1252
+ exports.enforceRuntimeFallbackSignalTrustPolicy = __webpack_exports__.enforceRuntimeFallbackSignalTrustPolicy;
1253
+ exports.getRuntimeSignalErrorStatusCode = __webpack_exports__.getRuntimeSignalErrorStatusCode;
1254
+ exports.hasEnabledTelemetryExporters = __webpack_exports__.hasEnabledTelemetryExporters;
1255
+ exports.injectTelemetryPlugin = __webpack_exports__.injectTelemetryPlugin;
1256
+ exports.normalizeRuntimeFallbackSignalAuthConfig = __webpack_exports__.normalizeRuntimeFallbackSignalAuthConfig;
1257
+ exports.normalizeRuntimeFallbackTrustPolicy = __webpack_exports__.normalizeRuntimeFallbackTrustPolicy;
1258
+ exports.parseRuntimeFallbackSignalPayloadFromRawBody = __webpack_exports__.parseRuntimeFallbackSignalPayloadFromRawBody;
1259
+ exports.resolveRuntimeFallbackSignalEndpoint = __webpack_exports__.resolveRuntimeFallbackSignalEndpoint;
1260
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
1261
+ "DEFAULT_RUNTIME_FALLBACK_SIGNAL_ENDPOINT",
1262
+ "DEFAULT_RUNTIME_STATUS_ENDPOINT",
1263
+ "TelemetryCanaryOrchestrator",
1264
+ "TelemetryRegistry",
1265
+ "TelemetryStartupHealthError",
1266
+ "createOtlpTelemetryExporter",
1267
+ "createRuntimeFallbackSignalRuntimeState",
1268
+ "createRuntimeSignalError",
1269
+ "createTelemetryAwareMetrics",
1270
+ "createVictoriaMetricsTelemetryExporter",
1271
+ "enforceRuntimeFallbackSignalAuthToken",
1272
+ "enforceRuntimeFallbackSignalTrustPolicy",
1273
+ "getRuntimeSignalErrorStatusCode",
1274
+ "hasEnabledTelemetryExporters",
1275
+ "injectTelemetryPlugin",
1276
+ "normalizeRuntimeFallbackSignalAuthConfig",
1277
+ "normalizeRuntimeFallbackTrustPolicy",
1278
+ "parseRuntimeFallbackSignalPayloadFromRawBody",
1279
+ "resolveRuntimeFallbackSignalEndpoint"
1280
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
1281
+ Object.defineProperty(exports, '__esModule', {
1282
+ value: true
1283
+ });