@creezio/observability 0.22.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 (209) hide show
  1. package/README.md +328 -0
  2. package/dist/.creezio-src-hash.json +4 -0
  3. package/dist/api-endpoints/http-routes.d.ts +11 -0
  4. package/dist/api-endpoints/http-routes.d.ts.map +1 -0
  5. package/dist/api-endpoints/http-routes.js +11 -0
  6. package/dist/api-endpoints/http-routes.js.map +1 -0
  7. package/dist/api-endpoints/index.d.ts +4 -0
  8. package/dist/api-endpoints/index.d.ts.map +1 -0
  9. package/dist/api-endpoints/index.js +3 -0
  10. package/dist/api-endpoints/index.js.map +1 -0
  11. package/dist/api-endpoints/registry.d.ts +66 -0
  12. package/dist/api-endpoints/registry.d.ts.map +1 -0
  13. package/dist/api-endpoints/registry.js +102 -0
  14. package/dist/api-endpoints/registry.js.map +1 -0
  15. package/dist/api-mount.d.ts +7 -0
  16. package/dist/api-mount.d.ts.map +1 -0
  17. package/dist/api-mount.js +114 -0
  18. package/dist/api-mount.js.map +1 -0
  19. package/dist/helpers.d.ts +23 -0
  20. package/dist/helpers.d.ts.map +1 -0
  21. package/dist/helpers.js +36 -0
  22. package/dist/helpers.js.map +1 -0
  23. package/dist/index.d.ts +35 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +24 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/memory-store.d.ts +3 -0
  28. package/dist/memory-store.d.ts.map +1 -0
  29. package/dist/memory-store.js +113 -0
  30. package/dist/memory-store.js.map +1 -0
  31. package/dist/ops/emit.d.ts +8 -0
  32. package/dist/ops/emit.d.ts.map +1 -0
  33. package/dist/ops/emit.js +15 -0
  34. package/dist/ops/emit.js.map +1 -0
  35. package/dist/ops/fleet-activity.d.ts +50 -0
  36. package/dist/ops/fleet-activity.d.ts.map +1 -0
  37. package/dist/ops/fleet-activity.js +123 -0
  38. package/dist/ops/fleet-activity.js.map +1 -0
  39. package/dist/ops/fleet-agent.d.ts +102 -0
  40. package/dist/ops/fleet-agent.d.ts.map +1 -0
  41. package/dist/ops/fleet-agent.js +352 -0
  42. package/dist/ops/fleet-agent.js.map +1 -0
  43. package/dist/ops/fleet-samples.d.ts +33 -0
  44. package/dist/ops/fleet-samples.d.ts.map +1 -0
  45. package/dist/ops/fleet-samples.js +223 -0
  46. package/dist/ops/fleet-samples.js.map +1 -0
  47. package/dist/ops/journal.d.ts +56 -0
  48. package/dist/ops/journal.d.ts.map +1 -0
  49. package/dist/ops/journal.js +307 -0
  50. package/dist/ops/journal.js.map +1 -0
  51. package/dist/ops/rules.d.ts +16 -0
  52. package/dist/ops/rules.d.ts.map +1 -0
  53. package/dist/ops/rules.js +98 -0
  54. package/dist/ops/rules.js.map +1 -0
  55. package/dist/ops/types.d.ts +69 -0
  56. package/dist/ops/types.d.ts.map +1 -0
  57. package/dist/ops/types.js +119 -0
  58. package/dist/ops/types.js.map +1 -0
  59. package/dist/request-logs/config.d.ts +19 -0
  60. package/dist/request-logs/config.d.ts.map +1 -0
  61. package/dist/request-logs/config.js +36 -0
  62. package/dist/request-logs/config.js.map +1 -0
  63. package/dist/request-logs/http-routes.d.ts +8 -0
  64. package/dist/request-logs/http-routes.d.ts.map +1 -0
  65. package/dist/request-logs/http-routes.js +29 -0
  66. package/dist/request-logs/http-routes.js.map +1 -0
  67. package/dist/request-logs/index.d.ts +6 -0
  68. package/dist/request-logs/index.d.ts.map +1 -0
  69. package/dist/request-logs/index.js +5 -0
  70. package/dist/request-logs/index.js.map +1 -0
  71. package/dist/request-logs/middleware.d.ts +11 -0
  72. package/dist/request-logs/middleware.d.ts.map +1 -0
  73. package/dist/request-logs/middleware.js +198 -0
  74. package/dist/request-logs/middleware.js.map +1 -0
  75. package/dist/request-logs/request-logs.d.ts +60 -0
  76. package/dist/request-logs/request-logs.d.ts.map +1 -0
  77. package/dist/request-logs/request-logs.js +260 -0
  78. package/dist/request-logs/request-logs.js.map +1 -0
  79. package/dist/schema.d.ts +3 -0
  80. package/dist/schema.d.ts.map +1 -0
  81. package/dist/schema.js +21 -0
  82. package/dist/schema.js.map +1 -0
  83. package/dist/sqlite-driver.d.ts +16 -0
  84. package/dist/sqlite-driver.d.ts.map +1 -0
  85. package/dist/sqlite-driver.js +15 -0
  86. package/dist/sqlite-driver.js.map +1 -0
  87. package/dist/sqlite-store.d.ts +12 -0
  88. package/dist/sqlite-store.d.ts.map +1 -0
  89. package/dist/sqlite-store.js +176 -0
  90. package/dist/sqlite-store.js.map +1 -0
  91. package/dist/types.d.ts +67 -0
  92. package/dist/types.d.ts.map +1 -0
  93. package/dist/types.js +9 -0
  94. package/dist/types.js.map +1 -0
  95. package/dist/usage/adapters.d.ts +31 -0
  96. package/dist/usage/adapters.d.ts.map +1 -0
  97. package/dist/usage/adapters.js +37 -0
  98. package/dist/usage/adapters.js.map +1 -0
  99. package/dist/usage/http-routes.d.ts +23 -0
  100. package/dist/usage/http-routes.d.ts.map +1 -0
  101. package/dist/usage/http-routes.js +150 -0
  102. package/dist/usage/http-routes.js.map +1 -0
  103. package/dist/usage/index.d.ts +11 -0
  104. package/dist/usage/index.d.ts.map +1 -0
  105. package/dist/usage/index.js +7 -0
  106. package/dist/usage/index.js.map +1 -0
  107. package/dist/usage/ui-brand.d.ts +23 -0
  108. package/dist/usage/ui-brand.d.ts.map +1 -0
  109. package/dist/usage/ui-brand.js +18 -0
  110. package/dist/usage/ui-brand.js.map +1 -0
  111. package/dist/usage/usage-analytics-productivity.d.ts +73 -0
  112. package/dist/usage/usage-analytics-productivity.d.ts.map +1 -0
  113. package/dist/usage/usage-analytics-productivity.js +317 -0
  114. package/dist/usage/usage-analytics-productivity.js.map +1 -0
  115. package/dist/usage/usage-analytics-shared.d.ts +5 -0
  116. package/dist/usage/usage-analytics-shared.d.ts.map +1 -0
  117. package/dist/usage/usage-analytics-shared.js +20 -0
  118. package/dist/usage/usage-analytics-shared.js.map +1 -0
  119. package/dist/usage/usage-analytics.d.ts +127 -0
  120. package/dist/usage/usage-analytics.d.ts.map +1 -0
  121. package/dist/usage/usage-analytics.js +338 -0
  122. package/dist/usage/usage-analytics.js.map +1 -0
  123. package/dist-cjs/api-endpoints/http-routes.js +14 -0
  124. package/dist-cjs/api-endpoints/http-routes.js.map +1 -0
  125. package/dist-cjs/api-endpoints/index.js +10 -0
  126. package/dist-cjs/api-endpoints/index.js.map +1 -0
  127. package/dist-cjs/api-endpoints/registry.js +107 -0
  128. package/dist-cjs/api-endpoints/registry.js.map +1 -0
  129. package/dist-cjs/api-mount.js +117 -0
  130. package/dist-cjs/api-mount.js.map +1 -0
  131. package/dist-cjs/helpers.js +41 -0
  132. package/dist-cjs/helpers.js.map +1 -0
  133. package/dist-cjs/index.js +118 -0
  134. package/dist-cjs/index.js.map +1 -0
  135. package/dist-cjs/memory-store.js +119 -0
  136. package/dist-cjs/memory-store.js.map +1 -0
  137. package/dist-cjs/ops/emit.js +18 -0
  138. package/dist-cjs/ops/emit.js.map +1 -0
  139. package/dist-cjs/ops/fleet-activity.js +131 -0
  140. package/dist-cjs/ops/fleet-activity.js.map +1 -0
  141. package/dist-cjs/ops/fleet-agent.js +358 -0
  142. package/dist-cjs/ops/fleet-agent.js.map +1 -0
  143. package/dist-cjs/ops/fleet-samples.js +229 -0
  144. package/dist-cjs/ops/fleet-samples.js.map +1 -0
  145. package/dist-cjs/ops/journal.js +326 -0
  146. package/dist-cjs/ops/journal.js.map +1 -0
  147. package/dist-cjs/ops/rules.js +102 -0
  148. package/dist-cjs/ops/rules.js.map +1 -0
  149. package/dist-cjs/ops/types.js +126 -0
  150. package/dist-cjs/ops/types.js.map +1 -0
  151. package/dist-cjs/package.json +3 -0
  152. package/dist-cjs/request-logs/config.js +42 -0
  153. package/dist-cjs/request-logs/config.js.map +1 -0
  154. package/dist-cjs/request-logs/http-routes.js +32 -0
  155. package/dist-cjs/request-logs/http-routes.js.map +1 -0
  156. package/dist-cjs/request-logs/index.js +27 -0
  157. package/dist-cjs/request-logs/index.js.map +1 -0
  158. package/dist-cjs/request-logs/middleware.js +203 -0
  159. package/dist-cjs/request-logs/middleware.js.map +1 -0
  160. package/dist-cjs/request-logs/request-logs.js +277 -0
  161. package/dist-cjs/request-logs/request-logs.js.map +1 -0
  162. package/dist-cjs/schema.js +24 -0
  163. package/dist-cjs/schema.js.map +1 -0
  164. package/dist-cjs/sqlite-driver.js +18 -0
  165. package/dist-cjs/sqlite-driver.js.map +1 -0
  166. package/dist-cjs/sqlite-store.js +182 -0
  167. package/dist-cjs/sqlite-store.js.map +1 -0
  168. package/dist-cjs/types.js +12 -0
  169. package/dist-cjs/types.js.map +1 -0
  170. package/dist-cjs/usage/adapters.js +47 -0
  171. package/dist-cjs/usage/adapters.js.map +1 -0
  172. package/dist-cjs/usage/http-routes.js +154 -0
  173. package/dist-cjs/usage/http-routes.js.map +1 -0
  174. package/dist-cjs/usage/index.js +34 -0
  175. package/dist-cjs/usage/index.js.map +1 -0
  176. package/dist-cjs/usage/ui-brand.js +23 -0
  177. package/dist-cjs/usage/ui-brand.js.map +1 -0
  178. package/dist-cjs/usage/usage-analytics-productivity.js +321 -0
  179. package/dist-cjs/usage/usage-analytics-productivity.js.map +1 -0
  180. package/dist-cjs/usage/usage-analytics-shared.js +23 -0
  181. package/dist-cjs/usage/usage-analytics-shared.js.map +1 -0
  182. package/dist-cjs/usage/usage-analytics.js +353 -0
  183. package/dist-cjs/usage/usage-analytics.js.map +1 -0
  184. package/fleet-collector/AGENTS.md +7 -0
  185. package/fleet-collector/README.md +83 -0
  186. package/fleet-collector/configure-fleet-npm.sh +108 -0
  187. package/fleet-collector/env.mjs +174 -0
  188. package/fleet-collector/ops-api.mjs +455 -0
  189. package/fleet-collector/public/admin.html +696 -0
  190. package/fleet-collector/public/index.html +941 -0
  191. package/fleet-collector/server.mjs +564 -0
  192. package/fleet-collector/test-fleet-collector.mjs +413 -0
  193. package/fleet-collector/test-server-admin.mjs +475 -0
  194. package/package.json +109 -0
  195. package/scripts/test-api-endpoints-registry.mjs +60 -0
  196. package/ui/analytics-client.tsx +834 -0
  197. package/ui/analytics-productivity-panel.tsx +513 -0
  198. package/ui/api-endpoints-client.tsx +228 -0
  199. package/ui/index.ts +39 -0
  200. package/ui/primitives/badge.tsx +37 -0
  201. package/ui/primitives/button.tsx +44 -0
  202. package/ui/primitives/card.tsx +44 -0
  203. package/ui/primitives/cn.ts +6 -0
  204. package/ui/primitives/input.tsx +19 -0
  205. package/ui/primitives/tabs.tsx +51 -0
  206. package/ui/request-logs-client.tsx +327 -0
  207. package/ui/session-usage-analytics-provider.tsx +28 -0
  208. package/ui/usage-analytics-client.ts +479 -0
  209. package/ui/usage-analytics-provider.tsx +84 -0
@@ -0,0 +1,338 @@
1
+ /**
2
+ * Analytics d'usage — persistance SQLite + agrégations Admin.
3
+ * Événements UI (pages, clics, dwell) + actions serveur (agent IA…).
4
+ */
5
+ import { uaGetWriteDb as getWriteDb, uaQueryAll as queryAll, uaQueryOne as queryOne, uaTableExists as tableExists, } from "./adapters.js";
6
+ import { formatDuration, } from "./usage-analytics-shared.js";
7
+ export { formatDuration };
8
+ let schemaReady = false;
9
+ export function usageAnalyticsReady() {
10
+ return tableExists("usage_events");
11
+ }
12
+ /** Crée la table si absente (dev / avant migration Electron). */
13
+ export function ensureUsageAnalyticsSchema() {
14
+ if (schemaReady && usageAnalyticsReady())
15
+ return;
16
+ const db = getWriteDb();
17
+ db.exec(`
18
+ CREATE TABLE IF NOT EXISTS usage_events (
19
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
20
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
21
+ event_type TEXT NOT NULL,
22
+ category TEXT NOT NULL DEFAULT 'ui',
23
+ label TEXT,
24
+ path TEXT,
25
+ referrer_path TEXT,
26
+ user_id TEXT,
27
+ username TEXT,
28
+ user_kind TEXT NOT NULL DEFAULT 'human',
29
+ user_role TEXT,
30
+ session_id TEXT,
31
+ duration_ms INTEGER,
32
+ meta_json TEXT,
33
+ user_agent TEXT,
34
+ surface TEXT NOT NULL DEFAULT 'crm'
35
+ );
36
+ CREATE INDEX IF NOT EXISTS idx_usage_events_created
37
+ ON usage_events(created_at);
38
+ CREATE INDEX IF NOT EXISTS idx_usage_events_user_created
39
+ ON usage_events(user_id, created_at);
40
+ CREATE INDEX IF NOT EXISTS idx_usage_events_type_created
41
+ ON usage_events(event_type, created_at);
42
+ CREATE INDEX IF NOT EXISTS idx_usage_events_path_created
43
+ ON usage_events(path, created_at);
44
+ CREATE INDEX IF NOT EXISTS idx_usage_events_kind_created
45
+ ON usage_events(user_kind, created_at);
46
+ CREATE INDEX IF NOT EXISTS idx_usage_events_session
47
+ ON usage_events(session_id, created_at);
48
+ `);
49
+ schemaReady = true;
50
+ }
51
+ function normalizeKind(v) {
52
+ const s = String(v || "").toLowerCase();
53
+ if (s === "ai")
54
+ return "ai";
55
+ if (s === "system")
56
+ return "system";
57
+ if (s === "human")
58
+ return "human";
59
+ return "unknown";
60
+ }
61
+ function clampStr(v, max) {
62
+ if (v == null)
63
+ return null;
64
+ const s = String(v).trim();
65
+ if (!s)
66
+ return null;
67
+ return s.slice(0, max);
68
+ }
69
+ function periodBounds(period, now = new Date()) {
70
+ const to = now.toISOString();
71
+ const d = new Date(now);
72
+ if (period === "day")
73
+ d.setUTCDate(d.getUTCDate() - 1);
74
+ else if (period === "week")
75
+ d.setUTCDate(d.getUTCDate() - 7);
76
+ else if (period === "month")
77
+ d.setUTCDate(d.getUTCDate() - 30);
78
+ else
79
+ d.setUTCFullYear(d.getUTCFullYear() - 1);
80
+ return { from: d.toISOString(), to };
81
+ }
82
+ function buildWhere(filters) {
83
+ const parts = ["1=1"];
84
+ const params = [];
85
+ if (filters.from) {
86
+ parts.push("created_at >= ?");
87
+ params.push(filters.from);
88
+ }
89
+ if (filters.to) {
90
+ parts.push("created_at <= ?");
91
+ params.push(filters.to);
92
+ }
93
+ if (filters.userId) {
94
+ parts.push("user_id = ?");
95
+ params.push(filters.userId);
96
+ }
97
+ if (filters.kind && filters.kind !== "all") {
98
+ parts.push("user_kind = ?");
99
+ params.push(filters.kind);
100
+ }
101
+ if (filters.eventType) {
102
+ parts.push("event_type = ?");
103
+ params.push(filters.eventType);
104
+ }
105
+ if (filters.path) {
106
+ parts.push("path LIKE ?");
107
+ params.push(`${filters.path}%`);
108
+ }
109
+ if (filters.q) {
110
+ parts.push("(label LIKE ? OR path LIKE ? OR username LIKE ? OR event_type LIKE ?)");
111
+ const like = `%${filters.q}%`;
112
+ params.push(like, like, like, like);
113
+ }
114
+ return { sql: parts.join(" AND "), params };
115
+ }
116
+ export function insertUsageEvents(events) {
117
+ if (!events.length)
118
+ return 0;
119
+ ensureUsageAnalyticsSchema();
120
+ const db = getWriteDb();
121
+ const stmt = db.prepare(`
122
+ INSERT INTO usage_events (
123
+ created_at, event_type, category, label, path, referrer_path,
124
+ user_id, username, user_kind, user_role, session_id,
125
+ duration_ms, meta_json, user_agent, surface
126
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
127
+ `);
128
+ const now = new Date().toISOString();
129
+ let inserted = 0;
130
+ const insertRows = (rows) => {
131
+ for (const e of rows) {
132
+ const eventType = clampStr(e.eventType, 80);
133
+ if (!eventType)
134
+ continue;
135
+ const duration = typeof e.durationMs === "number" && Number.isFinite(e.durationMs) && e.durationMs >= 0
136
+ ? Math.min(Math.round(e.durationMs), 86_400_000)
137
+ : null;
138
+ stmt.run(clampStr(e.createdAt, 40) || now, eventType, clampStr(e.category, 40) || "ui", clampStr(e.label, 240), clampStr(e.path, 500), clampStr(e.referrerPath, 500), clampStr(e.userId, 80), clampStr(e.username, 120), normalizeKind(e.userKind), clampStr(e.userRole, 40), clampStr(e.sessionId, 80), duration, e.meta ? JSON.stringify(e.meta).slice(0, 4000) : null, clampStr(e.userAgent, 300), clampStr(e.surface, 40) || "crm");
139
+ inserted += 1;
140
+ }
141
+ };
142
+ if (db.transaction)
143
+ db.transaction(insertRows)(events);
144
+ else
145
+ insertRows(events);
146
+ return inserted;
147
+ }
148
+ export function recordUsageEvent(event) {
149
+ try {
150
+ insertUsageEvents([event]);
151
+ }
152
+ catch {
153
+ /* ne jamais casser le flux métier */
154
+ }
155
+ }
156
+ export function resolvePeriodFilters(period, from, to) {
157
+ const p = ["day", "week", "month", "year"].includes(period)
158
+ ? period
159
+ : "week";
160
+ if (from || to) {
161
+ return { from: from || undefined, to: to || undefined };
162
+ }
163
+ return periodBounds(p);
164
+ }
165
+ export function getUsageOverview(filters) {
166
+ ensureUsageAnalyticsSchema();
167
+ const { sql, params } = buildWhere(filters);
168
+ const totals = queryOne(`SELECT
169
+ COUNT(*) AS events,
170
+ SUM(CASE WHEN event_type = 'page.view' THEN 1 ELSE 0 END) AS page_views,
171
+ SUM(CASE WHEN event_type = 'ui.click' THEN 1 ELSE 0 END) AS clicks,
172
+ COUNT(DISTINCT session_id) AS sessions,
173
+ COUNT(DISTINCT user_id) AS active_users,
174
+ COUNT(DISTINCT CASE WHEN user_kind = 'human' THEN user_id END) AS active_humans,
175
+ COUNT(DISTINCT CASE WHEN user_kind = 'ai' THEN user_id END) AS active_ai,
176
+ COALESCE(SUM(CASE WHEN duration_ms IS NOT NULL THEN duration_ms ELSE 0 END), 0) AS total_time_ms
177
+ FROM usage_events
178
+ WHERE ${sql}`, params);
179
+ const byKind = queryAll(`SELECT
180
+ user_kind AS kind,
181
+ COUNT(*) AS events,
182
+ COUNT(DISTINCT user_id) AS users,
183
+ COALESCE(SUM(CASE WHEN duration_ms IS NOT NULL THEN duration_ms ELSE 0 END), 0) AS time_ms
184
+ FROM usage_events
185
+ WHERE ${sql}
186
+ GROUP BY user_kind
187
+ ORDER BY events DESC`, params);
188
+ const sessions = totals?.sessions ?? 0;
189
+ const totalTimeMs = totals?.total_time_ms ?? 0;
190
+ return {
191
+ period: { from: filters.from || "", to: filters.to || "" },
192
+ totals: {
193
+ events: totals?.events ?? 0,
194
+ pageViews: totals?.page_views ?? 0,
195
+ clicks: totals?.clicks ?? 0,
196
+ sessions,
197
+ activeUsers: totals?.active_users ?? 0,
198
+ activeHumans: totals?.active_humans ?? 0,
199
+ activeAi: totals?.active_ai ?? 0,
200
+ totalTimeMs,
201
+ avgSessionTimeMs: sessions > 0 ? Math.round(totalTimeMs / sessions) : 0,
202
+ },
203
+ byKind: byKind.map((r) => ({
204
+ kind: r.kind,
205
+ events: r.events,
206
+ users: r.users,
207
+ timeMs: r.time_ms,
208
+ })),
209
+ };
210
+ }
211
+ function bucketExpr(period) {
212
+ if (period === "day")
213
+ return `strftime('%Y-%m-%d %H:00', created_at)`;
214
+ if (period === "year")
215
+ return `strftime('%Y-%m', created_at)`;
216
+ return `strftime('%Y-%m-%d', created_at)`;
217
+ }
218
+ export function getUsageTimeline(filters, period = "week") {
219
+ ensureUsageAnalyticsSchema();
220
+ const { sql, params } = buildWhere(filters);
221
+ const bucket = bucketExpr(period);
222
+ return queryAll(`SELECT
223
+ ${bucket} AS bucket,
224
+ COUNT(*) AS events,
225
+ SUM(CASE WHEN event_type = 'page.view' THEN 1 ELSE 0 END) AS page_views,
226
+ SUM(CASE WHEN event_type = 'ui.click' THEN 1 ELSE 0 END) AS clicks,
227
+ SUM(CASE WHEN user_kind = 'human' THEN 1 ELSE 0 END) AS humans,
228
+ SUM(CASE WHEN user_kind = 'ai' THEN 1 ELSE 0 END) AS ai,
229
+ COALESCE(SUM(CASE WHEN duration_ms IS NOT NULL THEN duration_ms ELSE 0 END), 0) AS time_ms
230
+ FROM usage_events
231
+ WHERE ${sql}
232
+ GROUP BY bucket
233
+ ORDER BY bucket ASC`, params).map((r) => ({
234
+ bucket: r.bucket,
235
+ events: r.events,
236
+ pageViews: r.page_views,
237
+ clicks: r.clicks,
238
+ humans: r.humans,
239
+ ai: r.ai,
240
+ timeMs: r.time_ms,
241
+ }));
242
+ }
243
+ export function getTopPages(filters, limit = 25) {
244
+ ensureUsageAnalyticsSchema();
245
+ const { sql, params } = buildWhere(filters);
246
+ return queryAll(`SELECT
247
+ COALESCE(path, '(inconnu)') AS path,
248
+ SUM(CASE WHEN event_type = 'page.view' THEN 1 ELSE 0 END) AS views,
249
+ COUNT(DISTINCT user_id) AS unique_users,
250
+ COALESCE(AVG(CASE WHEN event_type IN ('page.hide','page.dwell') AND duration_ms IS NOT NULL THEN duration_ms END), 0) AS avg_time_ms,
251
+ COALESCE(SUM(CASE WHEN duration_ms IS NOT NULL THEN duration_ms ELSE 0 END), 0) AS total_time_ms
252
+ FROM usage_events
253
+ WHERE ${sql} AND path IS NOT NULL AND path != ''
254
+ GROUP BY path
255
+ HAVING views > 0
256
+ ORDER BY views DESC
257
+ LIMIT ?`, [...params, Math.min(Math.max(limit, 1), 200)]).map((r) => ({
258
+ path: r.path,
259
+ views: r.views,
260
+ uniqueUsers: r.unique_users,
261
+ avgTimeMs: Math.round(r.avg_time_ms || 0),
262
+ totalTimeMs: r.total_time_ms,
263
+ }));
264
+ }
265
+ export function getTopClicks(filters, limit = 25) {
266
+ ensureUsageAnalyticsSchema();
267
+ const { sql, params } = buildWhere(filters);
268
+ return queryAll(`SELECT
269
+ COALESCE(NULLIF(TRIM(label), ''), '(sans label)') AS label,
270
+ COUNT(*) AS clicks,
271
+ COUNT(DISTINCT user_id) AS unique_users,
272
+ COUNT(DISTINCT path) AS paths
273
+ FROM usage_events
274
+ WHERE ${sql} AND event_type = 'ui.click'
275
+ GROUP BY label
276
+ ORDER BY clicks DESC
277
+ LIMIT ?`, [...params, Math.min(Math.max(limit, 1), 200)]).map((r) => ({
278
+ label: r.label,
279
+ clicks: r.clicks,
280
+ uniqueUsers: r.unique_users,
281
+ paths: r.paths,
282
+ }));
283
+ }
284
+ export function getUserStats(filters, limit = 50) {
285
+ ensureUsageAnalyticsSchema();
286
+ const { sql, params } = buildWhere(filters);
287
+ return queryAll(`SELECT
288
+ COALESCE(user_id, 'anonymous') AS user_id,
289
+ COALESCE(MAX(username), user_id, 'anonymous') AS username,
290
+ MAX(user_kind) AS kind,
291
+ MAX(user_role) AS role,
292
+ COUNT(*) AS events,
293
+ SUM(CASE WHEN event_type = 'page.view' THEN 1 ELSE 0 END) AS page_views,
294
+ SUM(CASE WHEN event_type = 'ui.click' THEN 1 ELSE 0 END) AS clicks,
295
+ COUNT(DISTINCT session_id) AS sessions,
296
+ COALESCE(SUM(CASE WHEN duration_ms IS NOT NULL THEN duration_ms ELSE 0 END), 0) AS time_ms,
297
+ MAX(created_at) AS last_seen
298
+ FROM usage_events
299
+ WHERE ${sql}
300
+ GROUP BY COALESCE(user_id, 'anonymous')
301
+ ORDER BY events DESC
302
+ LIMIT ?`, [...params, Math.min(Math.max(limit, 1), 200)]).map((r) => ({
303
+ userId: r.user_id,
304
+ username: r.username,
305
+ kind: r.kind,
306
+ role: r.role,
307
+ events: r.events,
308
+ pageViews: r.page_views,
309
+ clicks: r.clicks,
310
+ sessions: r.sessions,
311
+ timeMs: r.time_ms,
312
+ lastSeen: r.last_seen,
313
+ }));
314
+ }
315
+ export function listUsageEvents(filters) {
316
+ ensureUsageAnalyticsSchema();
317
+ const { sql, params } = buildWhere(filters);
318
+ const limit = Math.min(Math.max(filters.limit ?? 100, 1), 500);
319
+ const offset = Math.max(filters.offset ?? 0, 0);
320
+ const total = queryOne(`SELECT COUNT(*) AS c FROM usage_events WHERE ${sql}`, params)?.c ??
321
+ 0;
322
+ const events = queryAll(`SELECT * FROM usage_events WHERE ${sql} ORDER BY created_at DESC, id DESC LIMIT ? OFFSET ?`, [...params, limit, offset]);
323
+ return { events, total };
324
+ }
325
+ export function purgeUsageEvents(opts = {}) {
326
+ ensureUsageAnalyticsSchema();
327
+ const db = getWriteDb();
328
+ if (opts.all) {
329
+ const info = db.prepare(`DELETE FROM usage_events`).run();
330
+ return info.changes;
331
+ }
332
+ if (opts.before) {
333
+ const info = db.prepare(`DELETE FROM usage_events WHERE created_at < ?`).run(opts.before);
334
+ return info.changes;
335
+ }
336
+ return 0;
337
+ }
338
+ //# sourceMappingURL=usage-analytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage-analytics.js","sourceRoot":"","sources":["../../src/usage/usage-analytics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createApiEndpointsRoutes = createApiEndpointsRoutes;
4
+ /**
5
+ * Admin — registre des endpoints runtime (session UI).
6
+ * Hono « nu » : hors doc OpenAPI publique. Auth owner reste côté marque.
7
+ */
8
+ const hono_1 = require("hono");
9
+ function createApiEndpointsRoutes(opts) {
10
+ const app = new hono_1.Hono();
11
+ app.get("/endpoints", (c) => c.json(opts.getRegistry()));
12
+ return app;
13
+ }
14
+ //# sourceMappingURL=http-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-routes.js","sourceRoot":"","sources":["../../src/api-endpoints/http-routes.ts"],"names":[],"mappings":";;AAWA,4DAQC;AAnBD;;;GAGG;AACH,+BAA4B;AAO5B,SAAgB,wBAAwB,CACtC,IAAqC;IAErC,MAAM,GAAG,GAAG,IAAI,WAAI,EAAE,CAAC;IAEvB,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAEzD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createApiEndpointsRoutes = exports.collectHonoRoutes = exports.buildOpenApiDocumentFromRegistry = exports.buildApiEndpointsRegistry = void 0;
4
+ var registry_js_1 = require("./registry.js");
5
+ Object.defineProperty(exports, "buildApiEndpointsRegistry", { enumerable: true, get: function () { return registry_js_1.buildApiEndpointsRegistry; } });
6
+ Object.defineProperty(exports, "buildOpenApiDocumentFromRegistry", { enumerable: true, get: function () { return registry_js_1.buildOpenApiDocumentFromRegistry; } });
7
+ Object.defineProperty(exports, "collectHonoRoutes", { enumerable: true, get: function () { return registry_js_1.collectHonoRoutes; } });
8
+ var http_routes_js_1 = require("./http-routes.js");
9
+ Object.defineProperty(exports, "createApiEndpointsRoutes", { enumerable: true, get: function () { return http_routes_js_1.createApiEndpointsRoutes; } });
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api-endpoints/index.ts"],"names":[],"mappings":";;;AAKA,6CAIuB;AAHrB,wHAAA,yBAAyB,OAAA;AACzB,+HAAA,gCAAgC,OAAA;AAChC,gHAAA,iBAAiB,OAAA;AAEnB,mDAG0B;AAFxB,0HAAA,wBAAwB,OAAA"}
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ /**
3
+ * Registre Admin des endpoints runtime (port TempoFlow O5 — gold).
4
+ * Enrichit les routes réellement montées avec les métadonnées OpenAPI
5
+ * quand un document est fourni.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.buildApiEndpointsRegistry = buildApiEndpointsRegistry;
9
+ exports.buildOpenApiDocumentFromRegistry = buildOpenApiDocumentFromRegistry;
10
+ exports.collectHonoRoutes = collectHonoRoutes;
11
+ const HTTP_METHODS = [
12
+ "get",
13
+ "post",
14
+ "put",
15
+ "patch",
16
+ "delete",
17
+ "options",
18
+ "head",
19
+ ];
20
+ function buildApiEndpointsRegistry(opts) {
21
+ const operations = new Map();
22
+ for (const [pathKey, pathItem] of Object.entries(opts.openApiDocument?.paths || {})) {
23
+ if (!pathItem)
24
+ continue;
25
+ for (const method of HTTP_METHODS) {
26
+ const operation = pathItem[method];
27
+ if (!operation)
28
+ continue;
29
+ const normalizedPath = pathKey.replace(/\{([^}]+)\}/g, ":$1");
30
+ operations.set(`${method.toUpperCase()} ${normalizedPath}`, {
31
+ summary: operation.summary,
32
+ description: operation.description,
33
+ tags: operation.tags,
34
+ documented: true,
35
+ });
36
+ }
37
+ }
38
+ const seen = new Set();
39
+ const endpoints = opts.routes
40
+ .filter((route) => route.method && route.method !== "ALL")
41
+ .flatMap((route) => {
42
+ const method = route.method.toUpperCase();
43
+ const key = `${method} ${route.path}`;
44
+ if (seen.has(key))
45
+ return [];
46
+ seen.add(key);
47
+ const operation = operations.get(key);
48
+ return [
49
+ {
50
+ method,
51
+ path: route.path,
52
+ documented: Boolean(operation) || Boolean(route.description || route.summary),
53
+ summary: operation?.summary || route.summary || null,
54
+ description: operation?.description || route.description || null,
55
+ tags: operation?.tags?.length
56
+ ? operation.tags
57
+ : route.tags || [],
58
+ },
59
+ ];
60
+ })
61
+ .sort((a, b) => a.path.localeCompare(b.path) || a.method.localeCompare(b.method));
62
+ return {
63
+ generatedAt: new Date().toISOString(),
64
+ source: opts.source || "runtime routes (+ OpenAPI si fourni)",
65
+ openapiUrl: opts.openapiUrl || "/api/v1/openapi.json",
66
+ endpoints,
67
+ };
68
+ }
69
+ /** Document OpenAPI 3 minimal dérivé du registre runtime (lien Admin API). */
70
+ function buildOpenApiDocumentFromRegistry(registry, opts) {
71
+ const paths = {};
72
+ for (const ep of registry.endpoints) {
73
+ const method = ep.method.toLowerCase();
74
+ const pathKey = ep.path.replace(/:([A-Za-z0-9_]+)/g, "{$1}");
75
+ if (!paths[pathKey])
76
+ paths[pathKey] = {};
77
+ paths[pathKey][method] = {
78
+ summary: ep.summary || `${ep.method} ${ep.path}`,
79
+ ...(ep.description ? { description: ep.description } : {}),
80
+ tags: ep.tags.length ? ep.tags : ["runtime"],
81
+ responses: { "200": { description: "OK" } },
82
+ };
83
+ }
84
+ return {
85
+ openapi: "3.0.3",
86
+ info: {
87
+ title: opts?.title || "Creezio API",
88
+ version: opts?.version || "0.1.0",
89
+ description: `Generated from ${registry.source} at ${registry.generatedAt}`,
90
+ },
91
+ paths,
92
+ };
93
+ }
94
+ /** Collecte les routes d'une app Hono (y compris sous-apps montées). */
95
+ function collectHonoRoutes(app, pathPrefix = "") {
96
+ const prefix = pathPrefix.replace(/\/$/, "");
97
+ return app.routes
98
+ .filter((route) => route.method && route.method !== "ALL")
99
+ .map((route) => {
100
+ const sub = route.path.startsWith("/") ? route.path : `/${route.path}`;
101
+ const full = sub === "/"
102
+ ? prefix || "/"
103
+ : `${prefix}${sub}`.replace(/\/{2,}/g, "/");
104
+ return { method: route.method, path: full };
105
+ });
106
+ }
107
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/api-endpoints/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ /**
3
+ * Mount API observabilité — /api/v1/platform/observability/...
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createObservabilityApiMount = createObservabilityApiMount;
7
+ const types_js_1 = require("./types.js");
8
+ function asKind(v) {
9
+ const s = String(v || "");
10
+ return types_js_1.OBSERVABILITY_EVENT_KINDS.includes(s)
11
+ ? s
12
+ : undefined;
13
+ }
14
+ function createObservabilityApiMount(store) {
15
+ return {
16
+ handle: async ({ req, subPath }) => {
17
+ const method = req.method.toUpperCase();
18
+ const body = req.body && typeof req.body === "object"
19
+ ? req.body
20
+ : {};
21
+ if ((subPath === "" || subPath === "events") && method === "GET") {
22
+ const q = req.query || {};
23
+ const orgId = q.orgId != null ? String(q.orgId) : undefined;
24
+ const pluginId = q.pluginId != null ? String(q.pluginId) : undefined;
25
+ const action = q.action != null ? String(q.action) : undefined;
26
+ const since = q.since != null ? String(q.since) : undefined;
27
+ const kind = asKind(q.kind);
28
+ const limit = q.limit != null ? Number(q.limit) : 100;
29
+ const events = store.list({
30
+ kind,
31
+ orgId,
32
+ pluginId,
33
+ action,
34
+ since,
35
+ limit,
36
+ });
37
+ return {
38
+ status: 200,
39
+ body: {
40
+ ok: true,
41
+ count: events.length,
42
+ total: store.count({ kind, orgId, pluginId }),
43
+ events,
44
+ },
45
+ };
46
+ }
47
+ if (subPath === "events" && method === "POST") {
48
+ try {
49
+ const kind = asKind(body.kind);
50
+ if (!kind) {
51
+ return {
52
+ status: 400,
53
+ body: { ok: false, error: "kind invalide" },
54
+ };
55
+ }
56
+ const event = store.record({
57
+ kind,
58
+ action: String(body.action || "custom"),
59
+ orgId: body.orgId != null ? String(body.orgId) : null,
60
+ userId: body.userId != null ? String(body.userId) : null,
61
+ brandId: body.brandId != null ? String(body.brandId) : null,
62
+ pluginId: body.pluginId != null ? String(body.pluginId) : null,
63
+ meta: body.meta && typeof body.meta === "object"
64
+ ? body.meta
65
+ : {},
66
+ });
67
+ return { status: 201, body: { ok: true, event } };
68
+ }
69
+ catch (e) {
70
+ return {
71
+ status: 400,
72
+ body: {
73
+ ok: false,
74
+ error: e instanceof Error ? e.message : "error",
75
+ },
76
+ };
77
+ }
78
+ }
79
+ if (subPath === "usage" && method === "GET") {
80
+ const q = req.query || {};
81
+ const usage = store.aggregatePluginUsage({
82
+ orgId: q.orgId != null ? String(q.orgId) : undefined,
83
+ since: q.since != null ? String(q.since) : undefined,
84
+ limit: q.limit != null ? Number(q.limit) : 50,
85
+ });
86
+ return { status: 200, body: { ok: true, usage } };
87
+ }
88
+ if (subPath === "orgs" && method === "GET") {
89
+ const q = req.query || {};
90
+ const orgs = store.aggregateOrgActivity({
91
+ since: q.since != null ? String(q.since) : undefined,
92
+ limit: q.limit != null ? Number(q.limit) : 50,
93
+ });
94
+ return { status: 200, body: { ok: true, orgs } };
95
+ }
96
+ if (subPath === "summary" && method === "GET") {
97
+ return {
98
+ status: 200,
99
+ body: {
100
+ ok: true,
101
+ summary: {
102
+ activity: store.count({ kind: "activity" }),
103
+ plugin_usage: store.count({ kind: "plugin_usage" }),
104
+ control_plane: store.count({ kind: "control_plane" }),
105
+ total: store.count(),
106
+ },
107
+ usage: store.aggregatePluginUsage({ limit: 20 }),
108
+ orgs: store.aggregateOrgActivity({ limit: 20 }),
109
+ recent: store.list({ limit: 20 }),
110
+ },
111
+ };
112
+ }
113
+ return { status: 404, body: { ok: false, error: "not_found" } };
114
+ },
115
+ };
116
+ }
117
+ //# sourceMappingURL=api-mount.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-mount.js","sourceRoot":"","sources":["../src/api-mount.ts"],"names":[],"mappings":"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"}