@adonis-agora/telescope 0.4.0 → 0.5.1

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 (198) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/configure.d.ts.map +1 -1
  3. package/dist/configure.js +6 -0
  4. package/dist/configure.js.map +1 -1
  5. package/dist/providers/telescope_ai_provider.d.ts +9 -1
  6. package/dist/providers/telescope_ai_provider.d.ts.map +1 -1
  7. package/dist/providers/telescope_ai_provider.js +22 -2
  8. package/dist/providers/telescope_ai_provider.js.map +1 -1
  9. package/dist/providers/telescope_alerts_provider.d.ts +1 -0
  10. package/dist/providers/telescope_alerts_provider.d.ts.map +1 -1
  11. package/dist/providers/telescope_alerts_provider.js +37 -1
  12. package/dist/providers/telescope_alerts_provider.js.map +1 -1
  13. package/dist/providers/telescope_mcp_provider.d.ts +26 -0
  14. package/dist/providers/telescope_mcp_provider.d.ts.map +1 -0
  15. package/dist/providers/telescope_mcp_provider.js +114 -0
  16. package/dist/providers/telescope_mcp_provider.js.map +1 -0
  17. package/dist/providers/telescope_provider.d.ts +8 -0
  18. package/dist/providers/telescope_provider.d.ts.map +1 -1
  19. package/dist/providers/telescope_provider.js +56 -1
  20. package/dist/providers/telescope_provider.js.map +1 -1
  21. package/dist/providers/telescope_ui_provider.d.ts +2 -0
  22. package/dist/providers/telescope_ui_provider.d.ts.map +1 -1
  23. package/dist/providers/telescope_ui_provider.js +106 -22
  24. package/dist/providers/telescope_ui_provider.js.map +1 -1
  25. package/dist/providers/telescope_watchers_provider.d.ts +13 -2
  26. package/dist/providers/telescope_watchers_provider.d.ts.map +1 -1
  27. package/dist/providers/telescope_watchers_provider.js +57 -7
  28. package/dist/providers/telescope_watchers_provider.js.map +1 -1
  29. package/dist/src/ai/define_config.d.ts +39 -7
  30. package/dist/src/ai/define_config.d.ts.map +1 -1
  31. package/dist/src/ai/define_config.js +14 -4
  32. package/dist/src/ai/define_config.js.map +1 -1
  33. package/dist/src/ai/diagnosis_coordinator.d.ts +106 -0
  34. package/dist/src/ai/diagnosis_coordinator.d.ts.map +1 -0
  35. package/dist/src/ai/diagnosis_coordinator.js +143 -0
  36. package/dist/src/ai/diagnosis_coordinator.js.map +1 -0
  37. package/dist/src/ai/factory.d.ts +8 -5
  38. package/dist/src/ai/factory.d.ts.map +1 -1
  39. package/dist/src/ai/factory.js +20 -8
  40. package/dist/src/ai/factory.js.map +1 -1
  41. package/dist/src/ai/index.d.ts +3 -1
  42. package/dist/src/ai/index.d.ts.map +1 -1
  43. package/dist/src/ai/index.js +3 -1
  44. package/dist/src/ai/index.js.map +1 -1
  45. package/dist/src/alerts/alert_rule.d.ts +79 -11
  46. package/dist/src/alerts/alert_rule.d.ts.map +1 -1
  47. package/dist/src/alerts/alerter.d.ts +11 -1
  48. package/dist/src/alerts/alerter.d.ts.map +1 -1
  49. package/dist/src/alerts/alerter.js +21 -1
  50. package/dist/src/alerts/alerter.js.map +1 -1
  51. package/dist/src/alerts/alerter_service.d.ts +103 -0
  52. package/dist/src/alerts/alerter_service.d.ts.map +1 -0
  53. package/dist/src/alerts/alerter_service.js +215 -0
  54. package/dist/src/alerts/alerter_service.js.map +1 -0
  55. package/dist/src/alerts/index.d.ts +4 -2
  56. package/dist/src/alerts/index.d.ts.map +1 -1
  57. package/dist/src/alerts/index.js +4 -2
  58. package/dist/src/alerts/index.js.map +1 -1
  59. package/dist/src/alerts/slack_format.d.ts.map +1 -1
  60. package/dist/src/alerts/slack_format.js +35 -2
  61. package/dist/src/alerts/slack_format.js.map +1 -1
  62. package/dist/src/client_errors/config.d.ts +66 -0
  63. package/dist/src/client_errors/config.d.ts.map +1 -0
  64. package/dist/src/client_errors/config.js +17 -0
  65. package/dist/src/client_errors/config.js.map +1 -0
  66. package/dist/src/client_errors/index.d.ts +5 -0
  67. package/dist/src/client_errors/index.d.ts.map +1 -0
  68. package/dist/src/client_errors/index.js +5 -0
  69. package/dist/src/client_errors/index.js.map +1 -0
  70. package/dist/src/client_errors/ingestor.d.ts +87 -0
  71. package/dist/src/client_errors/ingestor.d.ts.map +1 -0
  72. package/dist/src/client_errors/ingestor.js +135 -0
  73. package/dist/src/client_errors/ingestor.js.map +1 -0
  74. package/dist/src/client_errors/rate_limiter.d.ts +53 -0
  75. package/dist/src/client_errors/rate_limiter.d.ts.map +1 -0
  76. package/dist/src/client_errors/rate_limiter.js +83 -0
  77. package/dist/src/client_errors/rate_limiter.js.map +1 -0
  78. package/dist/src/client_errors/validation.d.ts +62 -0
  79. package/dist/src/client_errors/validation.d.ts.map +1 -0
  80. package/dist/src/client_errors/validation.js +109 -0
  81. package/dist/src/client_errors/validation.js.map +1 -0
  82. package/dist/src/define_config.d.ts +120 -0
  83. package/dist/src/define_config.d.ts.map +1 -1
  84. package/dist/src/define_config.js +41 -0
  85. package/dist/src/define_config.js.map +1 -1
  86. package/dist/src/entry.d.ts +20 -0
  87. package/dist/src/entry.d.ts.map +1 -1
  88. package/dist/src/entry.js +20 -0
  89. package/dist/src/entry.js.map +1 -1
  90. package/dist/src/index.d.ts +16 -3
  91. package/dist/src/index.d.ts.map +1 -1
  92. package/dist/src/index.js +15 -2
  93. package/dist/src/index.js.map +1 -1
  94. package/dist/src/mcp/define_config.d.ts +57 -0
  95. package/dist/src/mcp/define_config.d.ts.map +1 -0
  96. package/dist/src/mcp/define_config.js +35 -0
  97. package/dist/src/mcp/define_config.js.map +1 -0
  98. package/dist/src/mcp/index.d.ts +7 -0
  99. package/dist/src/mcp/index.d.ts.map +1 -0
  100. package/dist/src/mcp/index.js +7 -0
  101. package/dist/src/mcp/index.js.map +1 -0
  102. package/dist/src/mcp/server.d.ts +89 -0
  103. package/dist/src/mcp/server.d.ts.map +1 -0
  104. package/dist/src/mcp/server.js +279 -0
  105. package/dist/src/mcp/server.js.map +1 -0
  106. package/dist/src/metrics/pulse.d.ts +158 -0
  107. package/dist/src/metrics/pulse.d.ts.map +1 -0
  108. package/dist/src/metrics/pulse.js +414 -0
  109. package/dist/src/metrics/pulse.js.map +1 -0
  110. package/dist/src/overload_guard.d.ts +77 -0
  111. package/dist/src/overload_guard.d.ts.map +1 -0
  112. package/dist/src/overload_guard.js +134 -0
  113. package/dist/src/overload_guard.js.map +1 -0
  114. package/dist/src/pruner.d.ts +93 -0
  115. package/dist/src/pruner.d.ts.map +1 -0
  116. package/dist/src/pruner.js +120 -0
  117. package/dist/src/pruner.js.map +1 -0
  118. package/dist/src/registry.d.ts +26 -0
  119. package/dist/src/registry.d.ts.map +1 -1
  120. package/dist/src/registry.js +19 -0
  121. package/dist/src/registry.js.map +1 -1
  122. package/dist/src/service.d.ts +16 -1
  123. package/dist/src/service.d.ts.map +1 -1
  124. package/dist/src/service.js +19 -1
  125. package/dist/src/service.js.map +1 -1
  126. package/dist/src/stores/factory.d.ts.map +1 -1
  127. package/dist/src/stores/factory.js +8 -2
  128. package/dist/src/stores/factory.js.map +1 -1
  129. package/dist/src/telescope_middleware.d.ts.map +1 -1
  130. package/dist/src/telescope_middleware.js +3 -1
  131. package/dist/src/telescope_middleware.js.map +1 -1
  132. package/dist/src/ui/api.d.ts +9 -1
  133. package/dist/src/ui/api.d.ts.map +1 -1
  134. package/dist/src/ui/api.js +23 -1
  135. package/dist/src/ui/api.js.map +1 -1
  136. package/dist/src/ui/auth.d.ts +112 -0
  137. package/dist/src/ui/auth.d.ts.map +1 -0
  138. package/dist/src/ui/auth.js +130 -0
  139. package/dist/src/ui/auth.js.map +1 -0
  140. package/dist/src/ui/dashboard_auth.d.ts +34 -0
  141. package/dist/src/ui/dashboard_auth.d.ts.map +1 -0
  142. package/dist/src/ui/dashboard_auth.js +57 -0
  143. package/dist/src/ui/dashboard_auth.js.map +1 -0
  144. package/dist/src/ui/define_config.d.ts +15 -0
  145. package/dist/src/ui/define_config.d.ts.map +1 -1
  146. package/dist/src/ui/define_config.js +4 -0
  147. package/dist/src/ui/define_config.js.map +1 -1
  148. package/dist/src/ui/index.d.ts +7 -1
  149. package/dist/src/ui/index.d.ts.map +1 -1
  150. package/dist/src/ui/index.js +6 -1
  151. package/dist/src/ui/index.js.map +1 -1
  152. package/dist/src/ui/login_page.d.ts +23 -0
  153. package/dist/src/ui/login_page.d.ts.map +1 -0
  154. package/dist/src/ui/login_page.js +170 -0
  155. package/dist/src/ui/login_page.js.map +1 -0
  156. package/dist/src/ui/session_cookie.d.ts +42 -0
  157. package/dist/src/ui/session_cookie.d.ts.map +1 -0
  158. package/dist/src/ui/session_cookie.js +97 -0
  159. package/dist/src/ui/session_cookie.js.map +1 -0
  160. package/dist/src/watchers/define_config.d.ts +115 -12
  161. package/dist/src/watchers/define_config.d.ts.map +1 -1
  162. package/dist/src/watchers/define_config.js +48 -11
  163. package/dist/src/watchers/define_config.js.map +1 -1
  164. package/dist/src/watchers/http_client_watcher.d.ts +91 -31
  165. package/dist/src/watchers/http_client_watcher.d.ts.map +1 -1
  166. package/dist/src/watchers/http_client_watcher.js +161 -53
  167. package/dist/src/watchers/http_client_watcher.js.map +1 -1
  168. package/dist/src/watchers/index.d.ts +9 -5
  169. package/dist/src/watchers/index.d.ts.map +1 -1
  170. package/dist/src/watchers/index.js +6 -2
  171. package/dist/src/watchers/index.js.map +1 -1
  172. package/dist/src/watchers/lucid_query_watcher.d.ts +20 -2
  173. package/dist/src/watchers/lucid_query_watcher.d.ts.map +1 -1
  174. package/dist/src/watchers/lucid_query_watcher.js +44 -10
  175. package/dist/src/watchers/lucid_query_watcher.js.map +1 -1
  176. package/dist/src/watchers/profiling_watcher.d.ts +144 -0
  177. package/dist/src/watchers/profiling_watcher.d.ts.map +1 -0
  178. package/dist/src/watchers/profiling_watcher.js +231 -0
  179. package/dist/src/watchers/profiling_watcher.js.map +1 -0
  180. package/dist/src/watchers/query_family_hash.d.ts +7 -2
  181. package/dist/src/watchers/query_family_hash.d.ts.map +1 -1
  182. package/dist/src/watchers/query_family_hash.js +8 -3
  183. package/dist/src/watchers/query_family_hash.js.map +1 -1
  184. package/dist/src/watchers/record.d.ts.map +1 -1
  185. package/dist/src/watchers/record.js +4 -0
  186. package/dist/src/watchers/record.js.map +1 -1
  187. package/dist/src/watchers/schedule_watcher.d.ts +143 -0
  188. package/dist/src/watchers/schedule_watcher.d.ts.map +1 -0
  189. package/dist/src/watchers/schedule_watcher.js +195 -0
  190. package/dist/src/watchers/schedule_watcher.js.map +1 -0
  191. package/dist/stubs/config/telescope.stub +0 -65
  192. package/dist/stubs/config/telescope_ai.stub +0 -36
  193. package/dist/stubs/config/telescope_alerts.stub +0 -47
  194. package/dist/stubs/config/telescope_mcp.stub +0 -0
  195. package/dist/stubs/config/telescope_ui.stub +0 -53
  196. package/dist/stubs/config/telescope_watchers.stub +0 -41
  197. package/dist/stubs/database/migrations/create_telescope_entries_table.stub +2 -2
  198. package/package.json +12 -2
@@ -0,0 +1,170 @@
1
+ /**
2
+ * The built-in `dashboardAuth` login page (`GET <basePath>/login`). Deliberately a small,
3
+ * dependency-free, hand-authored HTML page — NOT part of the bundled dashboard SPA — so gating the
4
+ * dashboard shell doesn't require rebuilding or extending the bundled Vite app.
5
+ *
6
+ * `returnTo` and any error state are read CLIENT-SIDE from `location.search` (never server-echoed
7
+ * into the HTML), so this function's only per-request-ish input is `basePath` — a developer-
8
+ * controlled config value, not user input — and the page body is otherwise a static template.
9
+ * This sidesteps HTML-escaping entirely: there is no reflected query-param interpolation surface
10
+ * to get wrong.
11
+ *
12
+ * The visual language (dark zinc card, mono type, emerald accent) mirrors the Agora consoles so
13
+ * they feel like one family. The submit flow POSTs JSON via `fetch` and follows the JSON
14
+ * `redirectTo` it gets back (rather than a classic form POST + server redirect), which is why the
15
+ * markup keeps its own `<script>`.
16
+ *
17
+ * The password input has NO `required` attribute and the value is forwarded AS-IS (empty string
18
+ * when blank): the host's `login` hook — not this page — decides whether a password matters, so an
19
+ * email-only host (gate on username, ignore password) works with the same page as a host with real
20
+ * passwords.
21
+ */
22
+ export function renderLoginPage(basePath) {
23
+ const loginAction = `${basePath}/login`;
24
+ const defaultReturnTo = basePath === '' ? '/' : basePath;
25
+ return `<!doctype html>
26
+ <html lang="en">
27
+ <head>
28
+ <meta charset="utf-8" />
29
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
30
+ <meta name="robots" content="noindex, nofollow" />
31
+ <title>Sign in — Telescope</title>
32
+ <style>
33
+ :root { color-scheme: dark; }
34
+ * { box-sizing: border-box; }
35
+ body {
36
+ margin: 0;
37
+ min-height: 100vh;
38
+ display: flex;
39
+ align-items: center;
40
+ justify-content: center;
41
+ background: #09090b;
42
+ color: #e4e4e7;
43
+ font: 14px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
44
+ padding: 16px;
45
+ }
46
+ .card {
47
+ width: 100%;
48
+ max-width: 384px;
49
+ border: 1px solid #27272a;
50
+ background: #18181b;
51
+ border-radius: 8px;
52
+ padding: 32px;
53
+ box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.5);
54
+ }
55
+ .brand {
56
+ margin: 0 0 24px;
57
+ text-align: center;
58
+ font-size: 18px;
59
+ font-weight: 600;
60
+ color: #34d399;
61
+ }
62
+ form { display: flex; flex-direction: column; gap: 16px; }
63
+ label { display: flex; flex-direction: column; gap: 6px; }
64
+ .field-label {
65
+ font-size: 11px;
66
+ text-transform: uppercase;
67
+ letter-spacing: 0.05em;
68
+ color: #71717a;
69
+ }
70
+ input {
71
+ border-radius: 4px;
72
+ border: 1px solid #3f3f46;
73
+ background: #09090b;
74
+ color: #f4f4f5;
75
+ padding: 8px 12px;
76
+ font: inherit;
77
+ outline: none;
78
+ }
79
+ input:focus { border-color: rgb(52 211 153 / 0.6); }
80
+ #error {
81
+ display: none;
82
+ margin: 0;
83
+ font-size: 12px;
84
+ color: #fb7185;
85
+ }
86
+ button {
87
+ margin-top: 8px;
88
+ border-radius: 4px;
89
+ border: 1px solid rgb(52 211 153 / 0.4);
90
+ background: rgb(52 211 153 / 0.1);
91
+ color: #6ee7b7;
92
+ padding: 8px 12px;
93
+ font: inherit;
94
+ font-size: 12px;
95
+ font-weight: 500;
96
+ text-transform: uppercase;
97
+ letter-spacing: 0.05em;
98
+ cursor: pointer;
99
+ }
100
+ button:hover:not(:disabled) { background: rgb(52 211 153 / 0.2); }
101
+ button:disabled { opacity: 0.6; cursor: default; }
102
+ </style>
103
+ </head>
104
+ <body>
105
+ <div class="card">
106
+ <p class="brand">Telescope</p>
107
+ <form id="login-form" autocomplete="on">
108
+ <label>
109
+ <span class="field-label">Username</span>
110
+ <input id="username" name="username" type="text" autocomplete="username" required autofocus />
111
+ </label>
112
+ <label>
113
+ <span class="field-label">Password</span>
114
+ <input id="password" name="password" type="password" autocomplete="current-password" />
115
+ </label>
116
+ <p id="error" role="alert">Invalid username or password.</p>
117
+ <button id="submit" type="submit">Sign in</button>
118
+ </form>
119
+ </div>
120
+ <script>
121
+ (function () {
122
+ var LOGIN_ACTION = ${JSON.stringify(loginAction)};
123
+ var DEFAULT_RETURN_TO = ${JSON.stringify(defaultReturnTo)};
124
+ var params = new URLSearchParams(window.location.search);
125
+ var errorBox = document.getElementById('error');
126
+ if (params.get('error')) errorBox.style.display = 'block';
127
+
128
+ function sameOriginReturnTo(value) {
129
+ if (typeof value !== 'string' || value === '') return DEFAULT_RETURN_TO;
130
+ if (value.charAt(0) !== '/' || value.charAt(1) === '/' || value.indexOf('://') !== -1) {
131
+ return DEFAULT_RETURN_TO;
132
+ }
133
+ return value;
134
+ }
135
+
136
+ var form = document.getElementById('login-form');
137
+ var submitButton = document.getElementById('submit');
138
+ form.addEventListener('submit', function (event) {
139
+ event.preventDefault();
140
+ submitButton.disabled = true;
141
+ errorBox.style.display = 'none';
142
+ var returnTo = sameOriginReturnTo(params.get('returnTo'));
143
+ fetch(LOGIN_ACTION, {
144
+ method: 'POST',
145
+ headers: { 'content-type': 'application/json' },
146
+ credentials: 'same-origin',
147
+ body: JSON.stringify({
148
+ username: document.getElementById('username').value,
149
+ password: document.getElementById('password').value,
150
+ returnTo: returnTo,
151
+ }),
152
+ })
153
+ .then(function (response) {
154
+ if (!response.ok) throw new Error('unauthorized');
155
+ return response.json();
156
+ })
157
+ .then(function (data) {
158
+ window.location.href = data.redirectTo || DEFAULT_RETURN_TO;
159
+ })
160
+ .catch(function () {
161
+ errorBox.style.display = 'block';
162
+ submitButton.disabled = false;
163
+ });
164
+ });
165
+ })();
166
+ </script>
167
+ </body>
168
+ </html>`;
169
+ }
170
+ //# sourceMappingURL=login_page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login_page.js","sourceRoot":"","sources":["../../../src/ui/login_page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,MAAM,WAAW,GAAG,GAAG,QAAQ,QAAQ,CAAC;IACxC,MAAM,eAAe,GAAG,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;IACzD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAiGc,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;4BACtB,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA6CnD,CAAC;AACT,CAAC"}
@@ -0,0 +1,42 @@
1
+ /** The validated dashboard session attached to a request once its cookie verifies. */
2
+ export interface DashboardSession {
3
+ /** Stable user id (the session user's `id`). */
4
+ sub: string;
5
+ /** Optional display name. */
6
+ name?: string;
7
+ /** Free-form role strings; the dashboard does not interpret them. */
8
+ roles: string[];
9
+ /** Issued-at, epoch milliseconds. */
10
+ iat: number;
11
+ /** Expiry, epoch milliseconds. */
12
+ exp: number;
13
+ }
14
+ /** The session user the host `login` hook returns to mint a cookie. */
15
+ export interface DashboardSessionUser {
16
+ id: string;
17
+ name?: string;
18
+ roles?: string[];
19
+ }
20
+ export interface SignOptions {
21
+ secret: string;
22
+ ttlMs: number;
23
+ /** Injectable clock (epoch ms) for deterministic tests. Defaults to `Date.now()`. */
24
+ now?: number;
25
+ }
26
+ export interface VerifyOptions {
27
+ secret: string;
28
+ /** Injectable clock (epoch ms) for deterministic tests. Defaults to `Date.now()`. */
29
+ now?: number;
30
+ }
31
+ /**
32
+ * Sign a session into the cookie value `base64url(payload).base64url(hmac)`. Stateless
33
+ * HMAC-SHA256, no store, `node:crypto` only — no JWT dependency.
34
+ */
35
+ export declare function signSessionCookie(user: DashboardSessionUser, options: SignOptions): string;
36
+ /**
37
+ * Verify a cookie value and return the session, or `null` for anything that's tampered,
38
+ * malformed, or expired (past `exp` + a 30s grace). Constant-time signature comparison. NEVER
39
+ * throws — any parse failure yields `null`.
40
+ */
41
+ export declare function verifySessionCookie(value: string, options: VerifyOptions): DashboardSession | null;
42
+ //# sourceMappingURL=session_cookie.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session_cookie.d.ts","sourceRoot":"","sources":["../../../src/ui/session_cookie.ts"],"names":[],"mappings":"AAcA,sFAAsF;AACtF,MAAM,WAAW,gBAAgB;IAC/B,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,6BAA6B;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,kCAAkC;IAClC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,uEAAuE;AACvE,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,qFAAqF;IACrF,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,qFAAqF;IACrF,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAcD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM,CAY1F;AAeD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,aAAa,GACrB,gBAAgB,GAAG,IAAI,CA4BzB"}
@@ -0,0 +1,97 @@
1
+ import { createHmac, timingSafeEqual } from 'node:crypto';
2
+ /**
3
+ * Dependency-free, framework-light signed session cookie for the dashboard's
4
+ * built-in {@link file://./auth.ts dashboardAuth} mechanism. Stateless
5
+ * HMAC-SHA256 over `node:crypto` only (no JWT dependency, no store, no
6
+ * AdonisJS types) — ported verbatim from `@adonis-agora/durable`'s dashboard so
7
+ * the cookie format is identical across the Agora dashboards and this stays
8
+ * unit-testable without an `HttpContext`.
9
+ */
10
+ /** Clock-skew grace applied to `exp` so a marginally-late clock doesn't bounce a valid cookie. */
11
+ const EXP_GRACE_MS = 30_000;
12
+ function base64urlEncode(value) {
13
+ return Buffer.from(value, 'utf8').toString('base64url');
14
+ }
15
+ function base64urlDecode(value) {
16
+ return Buffer.from(value, 'base64url').toString('utf8');
17
+ }
18
+ function hmac(secret, payload) {
19
+ return createHmac('sha256', secret).update(payload).digest('base64url');
20
+ }
21
+ /**
22
+ * Sign a session into the cookie value `base64url(payload).base64url(hmac)`. Stateless
23
+ * HMAC-SHA256, no store, `node:crypto` only — no JWT dependency.
24
+ */
25
+ export function signSessionCookie(user, options) {
26
+ const issuedAt = options.now ?? Date.now();
27
+ const session = {
28
+ sub: user.id,
29
+ ...(user.name !== undefined ? { name: user.name } : {}),
30
+ roles: user.roles ?? [],
31
+ iat: issuedAt,
32
+ exp: issuedAt + options.ttlMs,
33
+ };
34
+ const encodedPayload = base64urlEncode(JSON.stringify(session));
35
+ const signature = hmac(options.secret, encodedPayload);
36
+ return `${encodedPayload}.${signature}`;
37
+ }
38
+ /** Type guard for the decoded payload shape — defends against tampered/legacy payloads. */
39
+ function isSessionPayload(value) {
40
+ if (typeof value !== 'object' || value === null)
41
+ return false;
42
+ const record = { ...value };
43
+ if (typeof record.sub !== 'string')
44
+ return false;
45
+ if (record.name !== undefined && typeof record.name !== 'string')
46
+ return false;
47
+ if (!Array.isArray(record.roles))
48
+ return false;
49
+ if (!record.roles.every((role) => typeof role === 'string'))
50
+ return false;
51
+ if (typeof record.iat !== 'number' || !Number.isFinite(record.iat))
52
+ return false;
53
+ if (typeof record.exp !== 'number' || !Number.isFinite(record.exp))
54
+ return false;
55
+ return true;
56
+ }
57
+ /**
58
+ * Verify a cookie value and return the session, or `null` for anything that's tampered,
59
+ * malformed, or expired (past `exp` + a 30s grace). Constant-time signature comparison. NEVER
60
+ * throws — any parse failure yields `null`.
61
+ */
62
+ export function verifySessionCookie(value, options) {
63
+ try {
64
+ const dot = value.indexOf('.');
65
+ if (dot <= 0 || dot === value.length - 1)
66
+ return null;
67
+ const encodedPayload = value.slice(0, dot);
68
+ const providedSignature = value.slice(dot + 1);
69
+ const expectedSignature = hmac(options.secret, encodedPayload);
70
+ const provided = Buffer.from(providedSignature, 'base64url');
71
+ const expected = Buffer.from(expectedSignature, 'base64url');
72
+ // timingSafeEqual throws on a length mismatch — guard it so a wrong-length (tampered)
73
+ // signature returns null instead of throwing.
74
+ if (provided.length !== expected.length)
75
+ return null;
76
+ if (!timingSafeEqual(provided, expected))
77
+ return null;
78
+ const decoded = JSON.parse(base64urlDecode(encodedPayload));
79
+ if (!isSessionPayload(decoded))
80
+ return null;
81
+ const now = options.now ?? Date.now();
82
+ if (now > decoded.exp + EXP_GRACE_MS)
83
+ return null;
84
+ const session = {
85
+ sub: decoded.sub,
86
+ ...(decoded.name !== undefined ? { name: decoded.name } : {}),
87
+ roles: decoded.roles,
88
+ iat: decoded.iat,
89
+ exp: decoded.exp,
90
+ };
91
+ return session;
92
+ }
93
+ catch {
94
+ return null;
95
+ }
96
+ }
97
+ //# sourceMappingURL=session_cookie.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session_cookie.js","sourceRoot":"","sources":["../../../src/ui/session_cookie.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,107 @@
1
1
  /**
2
- * NOTE — no `'schedule'` watcher is shipped, intentionally. The NestJS original
3
- * (`@dudousxd/nestjs-telescope`'s schedule package) wraps `@nestjs/schedule`'s
4
- * `@Cron`/`@Interval`/`@Timeout` decorators via its `SchedulerRegistry`. AdonisJS
5
- * has NO first-party scheduler, and the popular community schedulers
6
- * (`adonisjs-scheduler` et al.) emit nothing on the app emitter and expose no
7
- * lifecycle hooks — so a generic schedule watcher could only be built by inventing
8
- * /wrapping a private API. It is therefore deliberately omitted. In the Agora
9
- * ecosystem, `@adonis-agora/durable` already bridges its scheduled/cron + workflow
10
- * run events onto the diagnostics bus, which the generic {@link DiagnosticsWatcher}
11
- * records — so scheduled-run observability is covered there, not by a bespoke
12
- * schedule watcher.
2
+ * NOTE — the `'schedule'` watcher is EXPLICIT-integration, by design. The NestJS
3
+ * original (`@dudousxd/nestjs-telescope`'s schedule package) wraps
4
+ * `@nestjs/schedule`'s `@Cron`/`@Interval`/`@Timeout` decorators via its
5
+ * `SchedulerRegistry`. AdonisJS has NO first-party scheduler, and the community
6
+ * schedulers (`adonisjs-scheduler` et al.) emit nothing on the app emitter and
7
+ * expose no lifecycle hook — so there is no stable event to tap. Rather than
8
+ * fabricate one, the schedule watcher's integration point is an explicit wrapper:
9
+ * `scheduleTask(name, fn)` (times a scheduled closure) / `recordScheduledRun(...)`
10
+ * (record an outcome you already have) — see `schedule_watcher.ts`. Enabling it
11
+ * publishes the config-backed default those helpers inherit. (In the Agora
12
+ * ecosystem, `@adonis-agora/durable` also bridges its scheduled/cron runs onto the
13
+ * diagnostics bus, which the {@link DiagnosticsWatcher} records.)
14
+ *
15
+ * The `'profiling'` watcher is likewise user-driven — there is no event to tap.
16
+ * Enabling it publishes the default backing the `profile(label, fn)` /
17
+ * `startProfile(label)` helpers (see `profiling_watcher.ts`); while disabled those
18
+ * helpers are a zero-cost no-op.
13
19
  */
14
20
  /** The per-technology watchers this package ships. */
15
- export type WatcherName = 'query' | 'mail' | 'cache' | 'http-client' | 'logs' | 'queue' | 'events' | 'redis';
21
+ export type WatcherName = 'query' | 'mail' | 'cache' | 'http-client' | 'logs' | 'queue' | 'events' | 'redis' | 'profiling' | 'schedule';
22
+ /**
23
+ * Tuning for the `http-client` (outbound) watcher. Outbound HTTP is opt-in
24
+ * instrumentation (Adonis has no single built-in client, so nothing is
25
+ * monkey-patched): these values back a bare `instrumentFetch(fetch)` once the
26
+ * provider has wired the watcher.
27
+ */
28
+ export interface HttpClientWatcherConfig {
29
+ /** Outbound calls at/above this many ms get a `slow` tag. Default 1000. */
30
+ slowMs?: number;
31
+ /** Hosts (exact, case-insensitive; may include a port) whose calls are not recorded. */
32
+ ignoreHosts?: string[];
33
+ /** Record request/response body SIZES (bytes, never the bytes). Default `false`. */
34
+ captureBodies?: boolean;
35
+ }
36
+ /** The fully-resolved `http-client` watcher config (no optionals). */
37
+ export interface ResolvedHttpClientWatcherConfig {
38
+ slowMs: number;
39
+ ignoreHosts: string[];
40
+ captureBodies: boolean;
41
+ }
42
+ /**
43
+ * Tuning for the Lucid `query` watcher — the one enabled by default. It records
44
+ * every SQL query Lucid emits on `db:query`; these knobs govern how much of each
45
+ * query is kept and which are recorded at all.
46
+ */
47
+ export interface QueryWatcherConfig {
48
+ /** Queries at/above this many ms get a `slow` tag (feeds the Pulse slow-query
49
+ * card). Default 500. */
50
+ slowMs?: number;
51
+ /**
52
+ * Record the raw bound parameter VALUES. Bindings routinely carry PII / secrets
53
+ * (emails, tokens, password hashes), so by default they are redacted to
54
+ * `[REDACTED]` placeholders (arity preserved) and only the normalized SQL
55
+ * template is kept. Turn on to capture the real values. Default `false`.
56
+ */
57
+ captureBindings?: boolean;
58
+ /** Connection names (exact, case-insensitive) whose queries are NOT recorded —
59
+ * e.g. drop the telescope store's own connection from the timeline. */
60
+ ignoreConnections?: string[];
61
+ /**
62
+ * Normalize each SQL string (collapse whitespace, replace literals with `?`)
63
+ * into the `familyHash` grouping key so every execution of the same query
64
+ * template rolls up as one — the N+1 / slow-query grouping. Turn off to hash the
65
+ * raw SQL verbatim (no grouping across differing literals). Default `true`.
66
+ */
67
+ normalize?: boolean;
68
+ }
69
+ /** The fully-resolved `query` watcher config (no optionals). */
70
+ export interface ResolvedQueryWatcherConfig {
71
+ slowMs: number;
72
+ captureBindings: boolean;
73
+ ignoreConnections: string[];
74
+ normalize: boolean;
75
+ }
76
+ /**
77
+ * Tuning for the `profiling` watcher — user-instrumented timing spans recorded via
78
+ * the opt-in `profile()` / `startProfile()` helpers. Nothing is captured until the
79
+ * watcher is enabled and those helpers are called around a code section.
80
+ */
81
+ export interface ProfilingWatcherConfig {
82
+ /** Spans at/above this many ms get a `slow` tag. Default 100. */
83
+ slowMs?: number;
84
+ /** Spans below this many ms are discarded (too short to be worth an entry). Default 0. */
85
+ minDurationMs?: number;
86
+ }
87
+ /** The fully-resolved `profiling` watcher config (no optionals). */
88
+ export interface ResolvedProfilingWatcherConfig {
89
+ slowMs: number;
90
+ minDurationMs: number;
91
+ }
92
+ /**
93
+ * Tuning for the `schedule` watcher — scheduled-task runs recorded via the opt-in
94
+ * `scheduleTask()` / `recordScheduledRun()` helpers (AdonisJS ships no scheduler
95
+ * event to tap, so integration is explicit — see `schedule_watcher.ts`).
96
+ */
97
+ export interface ScheduleWatcherConfig {
98
+ /** Runs at/above this many ms get a `slow` tag. Default 1000. */
99
+ slowMs?: number;
100
+ }
101
+ /** The fully-resolved `schedule` watcher config (no optionals). */
102
+ export interface ResolvedScheduleWatcherConfig {
103
+ slowMs: number;
104
+ }
16
105
  /**
17
106
  * The shape of `config/telescope_watchers.ts`. Everything is optional: by default
18
107
  * only the Lucid `query` watcher is enabled (it is the one whose events are
@@ -34,13 +123,27 @@ export interface TelescopeWatchersConfig {
34
123
  * - `'queue'` — records `@adonisjs/queue` job executions (optional peer).
35
124
  * - `'events'` — records every event emitted through the core Emitter.
36
125
  * - `'redis'` — records `@adonisjs/redis` commands (optional peer).
126
+ * - `'profiling'` — publishes the `profile()`/`startProfile()` span helpers.
127
+ * - `'schedule'` — publishes the `scheduleTask()`/`recordScheduledRun()` helpers.
37
128
  */
38
129
  watchers?: WatcherName[];
130
+ /** Tuning for the Lucid `query` watcher (slow threshold, bindings, ignore-connections, normalize). */
131
+ query?: QueryWatcherConfig;
132
+ /** Tuning for the `http-client` watcher (slow threshold, ignore-hosts, body sizes). */
133
+ httpClient?: HttpClientWatcherConfig;
134
+ /** Tuning for the `profiling` watcher (slow-span threshold, min duration floor). */
135
+ profiling?: ProfilingWatcherConfig;
136
+ /** Tuning for the `schedule` watcher (slow-run threshold). */
137
+ schedule?: ScheduleWatcherConfig;
39
138
  }
40
139
  /** The fully-resolved watchers config the provider acts on (no optionals). */
41
140
  export interface ResolvedTelescopeWatchersConfig {
42
141
  enabled: boolean;
43
142
  watchers: Set<WatcherName>;
143
+ query: ResolvedQueryWatcherConfig;
144
+ httpClient: ResolvedHttpClientWatcherConfig;
145
+ profiling: ResolvedProfilingWatcherConfig;
146
+ schedule: ResolvedScheduleWatcherConfig;
44
147
  }
45
148
  /** The default set of enabled watchers — the verified Lucid query watcher only. */
46
149
  export declare const DEFAULT_WATCHERS: WatcherName[];
@@ -1 +1 @@
1
- {"version":3,"file":"define_config.d.ts","sourceRoot":"","sources":["../../../src/watchers/define_config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,sDAAsD;AACtD,MAAM,MAAM,WAAW,GACnB,OAAO,GACP,MAAM,GACN,OAAO,GACP,aAAa,GACb,MAAM,GACN,OAAO,GACP,QAAQ,GACR,OAAO,CAAC;AAEZ;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;CAC1B;AAED,8EAA8E;AAC9E,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;CAC5B;AAED,mFAAmF;AACnF,eAAO,MAAM,gBAAgB,EAAE,WAAW,EAAc,CAAC;AAEzD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,uBAAuB,GAAG,uBAAuB,CAErF;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAC3B,MAAM,GAAE,uBAA4B,GACnC,+BAA+B,CAKjC"}
1
+ {"version":3,"file":"define_config.d.ts","sourceRoot":"","sources":["../../../src/watchers/define_config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,sDAAsD;AACtD,MAAM,MAAM,WAAW,GACnB,OAAO,GACP,MAAM,GACN,OAAO,GACP,aAAa,GACb,MAAM,GACN,OAAO,GACP,QAAQ,GACR,OAAO,GACP,WAAW,GACX,UAAU,CAAC;AAEf;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wFAAwF;IACxF,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,oFAAoF;IACpF,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,sEAAsE;AACtE,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;CACxB;AAKD;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC;8BAC0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;4EACwE;IACxE,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,gEAAgE;AAChE,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,OAAO,CAAC;IACzB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;CACpB;AAMD;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0FAA0F;IAC1F,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,oEAAoE;AACpE,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;CACvB;AAKD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,mEAAmE;AACnE,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,MAAM,CAAC;CAChB;AAKD;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IAEzB,sGAAsG;IACtG,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAE3B,uFAAuF;IACvF,UAAU,CAAC,EAAE,uBAAuB,CAAC;IAErC,oFAAoF;IACpF,SAAS,CAAC,EAAE,sBAAsB,CAAC;IAEnC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAClC;AAED,8EAA8E;AAC9E,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;IAC3B,KAAK,EAAE,0BAA0B,CAAC;IAClC,UAAU,EAAE,+BAA+B,CAAC;IAC5C,SAAS,EAAE,8BAA8B,CAAC;IAC1C,QAAQ,EAAE,6BAA6B,CAAC;CACzC;AAED,mFAAmF;AACnF,eAAO,MAAM,gBAAgB,EAAE,WAAW,EAAc,CAAC;AAEzD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,uBAAuB,GAAG,uBAAuB,CAErF;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAC3B,MAAM,GAAE,uBAA4B,GACnC,+BAA+B,CA2BjC"}
@@ -1,16 +1,31 @@
1
1
  /**
2
- * NOTE — no `'schedule'` watcher is shipped, intentionally. The NestJS original
3
- * (`@dudousxd/nestjs-telescope`'s schedule package) wraps `@nestjs/schedule`'s
4
- * `@Cron`/`@Interval`/`@Timeout` decorators via its `SchedulerRegistry`. AdonisJS
5
- * has NO first-party scheduler, and the popular community schedulers
6
- * (`adonisjs-scheduler` et al.) emit nothing on the app emitter and expose no
7
- * lifecycle hooks — so a generic schedule watcher could only be built by inventing
8
- * /wrapping a private API. It is therefore deliberately omitted. In the Agora
9
- * ecosystem, `@adonis-agora/durable` already bridges its scheduled/cron + workflow
10
- * run events onto the diagnostics bus, which the generic {@link DiagnosticsWatcher}
11
- * records — so scheduled-run observability is covered there, not by a bespoke
12
- * schedule watcher.
2
+ * NOTE — the `'schedule'` watcher is EXPLICIT-integration, by design. The NestJS
3
+ * original (`@dudousxd/nestjs-telescope`'s schedule package) wraps
4
+ * `@nestjs/schedule`'s `@Cron`/`@Interval`/`@Timeout` decorators via its
5
+ * `SchedulerRegistry`. AdonisJS has NO first-party scheduler, and the community
6
+ * schedulers (`adonisjs-scheduler` et al.) emit nothing on the app emitter and
7
+ * expose no lifecycle hook — so there is no stable event to tap. Rather than
8
+ * fabricate one, the schedule watcher's integration point is an explicit wrapper:
9
+ * `scheduleTask(name, fn)` (times a scheduled closure) / `recordScheduledRun(...)`
10
+ * (record an outcome you already have) — see `schedule_watcher.ts`. Enabling it
11
+ * publishes the config-backed default those helpers inherit. (In the Agora
12
+ * ecosystem, `@adonis-agora/durable` also bridges its scheduled/cron runs onto the
13
+ * diagnostics bus, which the {@link DiagnosticsWatcher} records.)
14
+ *
15
+ * The `'profiling'` watcher is likewise user-driven — there is no event to tap.
16
+ * Enabling it publishes the default backing the `profile(label, fn)` /
17
+ * `startProfile(label)` helpers (see `profiling_watcher.ts`); while disabled those
18
+ * helpers are a zero-cost no-op.
13
19
  */
20
+ /** Default outbound slow-call threshold (ms). */
21
+ const DEFAULT_HTTP_CLIENT_SLOW_MS = 1000;
22
+ /** Default slow-query threshold (ms). Databases are hotter than outbound HTTP, so
23
+ * this is lower than the http-client default. */
24
+ const DEFAULT_QUERY_SLOW_MS = 500;
25
+ /** Default slow-span threshold (ms) for profiling. */
26
+ const DEFAULT_PROFILING_SLOW_MS = 100;
27
+ /** Default slow-run threshold (ms) for scheduled tasks. */
28
+ const DEFAULT_SCHEDULE_SLOW_MS = 1000;
14
29
  /** The default set of enabled watchers — the verified Lucid query watcher only. */
15
30
  export const DEFAULT_WATCHERS = ['query'];
16
31
  /**
@@ -22,9 +37,31 @@ export function defineConfig(config) {
22
37
  }
23
38
  /** Apply defaults to a (possibly partial) config. */
24
39
  export function resolveConfig(config = {}) {
40
+ const query = config.query ?? {};
41
+ const httpClient = config.httpClient ?? {};
42
+ const profiling = config.profiling ?? {};
43
+ const schedule = config.schedule ?? {};
25
44
  return {
26
45
  enabled: config.enabled ?? true,
27
46
  watchers: new Set(config.watchers ?? DEFAULT_WATCHERS),
47
+ query: {
48
+ slowMs: query.slowMs ?? DEFAULT_QUERY_SLOW_MS,
49
+ captureBindings: query.captureBindings ?? false,
50
+ ignoreConnections: query.ignoreConnections ?? [],
51
+ normalize: query.normalize ?? true,
52
+ },
53
+ httpClient: {
54
+ slowMs: httpClient.slowMs ?? DEFAULT_HTTP_CLIENT_SLOW_MS,
55
+ ignoreHosts: httpClient.ignoreHosts ?? [],
56
+ captureBodies: httpClient.captureBodies ?? false,
57
+ },
58
+ profiling: {
59
+ slowMs: profiling.slowMs ?? DEFAULT_PROFILING_SLOW_MS,
60
+ minDurationMs: Math.max(0, profiling.minDurationMs ?? 0),
61
+ },
62
+ schedule: {
63
+ slowMs: schedule.slowMs ?? DEFAULT_SCHEDULE_SLOW_MS,
64
+ },
28
65
  };
29
66
  }
30
67
  //# sourceMappingURL=define_config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"define_config.js","sourceRoot":"","sources":["../../../src/watchers/define_config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA6CH,mFAAmF;AACnF,MAAM,CAAC,MAAM,gBAAgB,GAAkB,CAAC,OAAO,CAAC,CAAC;AAEzD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAA+B;IAC1D,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,aAAa,CAC3B,SAAkC,EAAE;IAEpC,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,IAAI;QAC/B,QAAQ,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,gBAAgB,CAAC;KACvD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"define_config.js","sourceRoot":"","sources":["../../../src/watchers/define_config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAqCH,iDAAiD;AACjD,MAAM,2BAA2B,GAAG,IAAI,CAAC;AAsCzC;kDACkD;AAClD,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAoBlC,sDAAsD;AACtD,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAiBtC,2DAA2D;AAC3D,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAoDtC,mFAAmF;AACnF,MAAM,CAAC,MAAM,gBAAgB,GAAkB,CAAC,OAAO,CAAC,CAAC;AAEzD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAA+B;IAC1D,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,aAAa,CAC3B,SAAkC,EAAE;IAEpC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;IACjC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;IAC3C,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC;IACzC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;IACvC,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,IAAI;QAC/B,QAAQ,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,gBAAgB,CAAC;QACtD,KAAK,EAAE;YACL,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,qBAAqB;YAC7C,eAAe,EAAE,KAAK,CAAC,eAAe,IAAI,KAAK;YAC/C,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,IAAI,EAAE;YAChD,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI;SACnC;QACD,UAAU,EAAE;YACV,MAAM,EAAE,UAAU,CAAC,MAAM,IAAI,2BAA2B;YACxD,WAAW,EAAE,UAAU,CAAC,WAAW,IAAI,EAAE;YACzC,aAAa,EAAE,UAAU,CAAC,aAAa,IAAI,KAAK;SACjD;QACD,SAAS,EAAE;YACT,MAAM,EAAE,SAAS,CAAC,MAAM,IAAI,yBAAyB;YACrD,aAAa,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,aAAa,IAAI,CAAC,CAAC;SACzD;QACD,QAAQ,EAAE;YACR,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,wBAAwB;SACpD;KACF,CAAC;AACJ,CAAC"}