@felan-ai/ext-insights 0.0.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 (56) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +9 -0
  3. package/README.md +31 -0
  4. package/dist/analytics.d.ts +3 -0
  5. package/dist/analytics.d.ts.map +1 -0
  6. package/dist/analytics.js +555 -0
  7. package/dist/analytics.js.map +1 -0
  8. package/dist/cli.d.ts +21 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +70 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/contracts.d.ts +20 -0
  13. package/dist/contracts.d.ts.map +1 -0
  14. package/dist/contracts.js +2 -0
  15. package/dist/contracts.js.map +1 -0
  16. package/dist/facets.d.ts +19 -0
  17. package/dist/facets.d.ts.map +1 -0
  18. package/dist/facets.js +60 -0
  19. package/dist/facets.js.map +1 -0
  20. package/dist/generated/report-app.d.ts +4 -0
  21. package/dist/generated/report-app.d.ts.map +1 -0
  22. package/dist/generated/report-app.js +5 -0
  23. package/dist/generated/report-app.js.map +1 -0
  24. package/dist/index.d.ts +14 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +114 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/markdown.d.ts +3 -0
  29. package/dist/markdown.d.ts.map +1 -0
  30. package/dist/markdown.js +169 -0
  31. package/dist/markdown.js.map +1 -0
  32. package/dist/parser.d.ts +3 -0
  33. package/dist/parser.d.ts.map +1 -0
  34. package/dist/parser.js +309 -0
  35. package/dist/parser.js.map +1 -0
  36. package/dist/rage.d.ts +12 -0
  37. package/dist/rage.d.ts.map +1 -0
  38. package/dist/rage.js +35 -0
  39. package/dist/rage.js.map +1 -0
  40. package/dist/report-app/logo.d.ts +2 -0
  41. package/dist/report-app/logo.d.ts.map +1 -0
  42. package/dist/report-app/logo.js +2 -0
  43. package/dist/report-app/logo.js.map +1 -0
  44. package/dist/report-app/utils.d.ts +7 -0
  45. package/dist/report-app/utils.d.ts.map +1 -0
  46. package/dist/report-app/utils.js +60 -0
  47. package/dist/report-app/utils.js.map +1 -0
  48. package/dist/report.d.ts +3 -0
  49. package/dist/report.d.ts.map +1 -0
  50. package/dist/report.js +7 -0
  51. package/dist/report.js.map +1 -0
  52. package/dist/types.d.ts +354 -0
  53. package/dist/types.d.ts.map +1 -0
  54. package/dist/types.js +2 -0
  55. package/dist/types.js.map +1 -0
  56. package/package.json +55 -0
package/dist/parser.js ADDED
@@ -0,0 +1,309 @@
1
+ import path from "node:path";
2
+ import { detectRage } from "./rage.js";
3
+ const LANGUAGE_BY_EXTENSION = {
4
+ ".ts": "TypeScript",
5
+ ".tsx": "TypeScript",
6
+ ".js": "JavaScript",
7
+ ".jsx": "JavaScript",
8
+ ".json": "JSON",
9
+ ".md": "Markdown",
10
+ ".py": "Python",
11
+ ".go": "Go",
12
+ ".rs": "Rust",
13
+ ".css": "CSS",
14
+ ".html": "HTML",
15
+ ".sql": "SQL",
16
+ };
17
+ export function parseSessionTranscript(content, sourceId) {
18
+ try {
19
+ let sessionId = "";
20
+ let cwd = "";
21
+ let startTime = null;
22
+ let endTime = null;
23
+ let userMessages = 0;
24
+ let assistantMessages = 0;
25
+ let toolCallCount = 0;
26
+ let toolCallErrors = 0;
27
+ let totalInput = 0;
28
+ let totalOutput = 0;
29
+ let totalCacheRead = 0;
30
+ let totalCacheWrite = 0;
31
+ let totalTokens = 0;
32
+ let totalCost = 0;
33
+ let costInput = 0;
34
+ let costOutput = 0;
35
+ let costCacheRead = 0;
36
+ let costCacheWrite = 0;
37
+ const models = {};
38
+ const providers = {};
39
+ const thinkingLevels = {};
40
+ const toolUsage = {};
41
+ const stopReasons = {};
42
+ let currentModel = "unknown";
43
+ const rageHits = [];
44
+ const responseTimesMs = [];
45
+ const activityByHour = {};
46
+ const filesMentioned = new Set();
47
+ const languageCounts = {};
48
+ const toolErrorsByName = {};
49
+ const gitActivity = { commits: 0, pushes: 0, statusChecks: 0, diffs: 0 };
50
+ let lastUserMessageAt = null;
51
+ let userInterruptions = 0;
52
+ for (const line of content.split(/\r?\n/u)) {
53
+ if (!line.trim())
54
+ continue;
55
+ try {
56
+ const event = JSON.parse(line);
57
+ if (!startTime && event.timestamp)
58
+ startTime = new Date(event.timestamp);
59
+ if (event.timestamp)
60
+ endTime = new Date(event.timestamp);
61
+ const eventTime = event.timestamp ? new Date(event.timestamp) : null;
62
+ if (eventTime && event.type === "message") {
63
+ const hour = String(eventTime.getHours());
64
+ activityByHour[hour] = (activityByHour[hour] ?? 0) + 1;
65
+ }
66
+ if (event.type === "interrupt" || event.type === "user_interrupt" || event.type === "abort") {
67
+ userInterruptions++;
68
+ }
69
+ if (event.type === "session" || event.type === "session_info") {
70
+ const data = event;
71
+ if (data.id)
72
+ sessionId = data.id;
73
+ if (data.cwd)
74
+ cwd = data.cwd;
75
+ }
76
+ if (event.type === "model_change") {
77
+ const data = event;
78
+ if (data.modelId) {
79
+ models[data.modelId] = models[data.modelId] ?? { count: 0, tokens: 0, cost: 0 };
80
+ models[data.modelId].count++;
81
+ currentModel = data.modelId;
82
+ }
83
+ if (data.provider) {
84
+ providers[data.provider] = (providers[data.provider] ?? 0) + 1;
85
+ }
86
+ }
87
+ if (event.type === "thinking_level_change") {
88
+ const data = event;
89
+ if (data.thinkingLevel) {
90
+ thinkingLevels[data.thinkingLevel] = (thinkingLevels[data.thinkingLevel] ?? 0) + 1;
91
+ }
92
+ }
93
+ if (event.type === "message") {
94
+ const msg = event.message;
95
+ if (msg.role === "user") {
96
+ userMessages++;
97
+ lastUserMessageAt = eventTime;
98
+ // Collect rage hits with the message index for accurate per-message dedup
99
+ const textParts = [];
100
+ if (msg.content) {
101
+ for (const item of msg.content) {
102
+ if (item.type === "text" && item.text)
103
+ textParts.push(item.text);
104
+ }
105
+ }
106
+ const text = textParts.join(" ");
107
+ if (text) {
108
+ const hour = event.timestamp ? new Date(event.timestamp).getHours() : -1;
109
+ for (const hit of detectRage(text)) {
110
+ rageHits.push({ ...hit, hour, model: currentModel, msgIndex: userMessages });
111
+ }
112
+ }
113
+ }
114
+ else if (msg.role === "assistant") {
115
+ assistantMessages++;
116
+ if (eventTime && lastUserMessageAt) {
117
+ responseTimesMs.push(Math.max(0, eventTime.getTime() - lastUserMessageAt.getTime()));
118
+ lastUserMessageAt = null;
119
+ }
120
+ if (msg.usage) {
121
+ const input = msg.usage.input ?? 0;
122
+ const output = msg.usage.output ?? 0;
123
+ const cacheRead = msg.usage.cacheRead ?? 0;
124
+ const cacheWrite = msg.usage.cacheWrite ?? 0;
125
+ const tokens = msg.usage.totalTokens ?? (input + output + cacheRead);
126
+ const cost = msg.usage.cost?.total ?? 0;
127
+ totalInput += input;
128
+ totalOutput += output;
129
+ totalCacheRead += cacheRead;
130
+ totalCacheWrite += cacheWrite;
131
+ totalTokens += tokens;
132
+ totalCost += cost;
133
+ costInput += msg.usage.cost?.input ?? 0;
134
+ costOutput += msg.usage.cost?.output ?? 0;
135
+ costCacheRead += msg.usage.cost?.cacheRead ?? 0;
136
+ costCacheWrite += msg.usage.cost?.cacheWrite ?? 0;
137
+ if (msg.model) {
138
+ models[msg.model] = models[msg.model] ?? { count: 0, tokens: 0, cost: 0 };
139
+ models[msg.model].tokens += tokens;
140
+ models[msg.model].cost += cost;
141
+ }
142
+ }
143
+ if (msg.stopReason) {
144
+ stopReasons[msg.stopReason] = (stopReasons[msg.stopReason] ?? 0) + 1;
145
+ if (msg.stopReason.toLowerCase().includes("interrupt"))
146
+ userInterruptions++;
147
+ }
148
+ }
149
+ if (msg.content) {
150
+ for (const item of msg.content) {
151
+ if (item.type === "toolCall" && item.name) {
152
+ toolCallCount++;
153
+ toolUsage[item.name] = (toolUsage[item.name] ?? 0) + 1;
154
+ collectToolSignals(item.name, [item.input, item.args, item.arguments], filesMentioned, languageCounts, gitActivity);
155
+ }
156
+ if (item.type === "toolResult" && item.isError) {
157
+ toolCallErrors++;
158
+ recordToolError(toolErrorsByName, item.name);
159
+ }
160
+ }
161
+ }
162
+ if (msg.toolCalls) {
163
+ toolCallCount += msg.toolCalls.length;
164
+ for (const tc of msg.toolCalls) {
165
+ if (tc.name) {
166
+ toolUsage[tc.name] = (toolUsage[tc.name] ?? 0) + 1;
167
+ collectToolSignals(tc.name, [tc.input, tc.args, tc.arguments], filesMentioned, languageCounts, gitActivity);
168
+ }
169
+ }
170
+ }
171
+ if (msg.toolResults) {
172
+ for (const tr of msg.toolResults) {
173
+ if (tr.isError) {
174
+ toolCallErrors++;
175
+ recordToolError(toolErrorsByName, tr.name);
176
+ }
177
+ }
178
+ }
179
+ }
180
+ }
181
+ catch {
182
+ // Skip malformed lines
183
+ }
184
+ }
185
+ if (!startTime)
186
+ return null;
187
+ if (!endTime)
188
+ endTime = startTime;
189
+ const duration = Math.max(1, Math.round((endTime.getTime() - startTime.getTime()) / 60000));
190
+ const projectName = cwd ? portableBasename(cwd) : "unknown";
191
+ const primaryModel = getPrimaryModel(models, currentModel);
192
+ const avgResponseTimeMs = responseTimesMs.length > 0
193
+ ? Math.round(responseTimesMs.reduce((sum, value) => sum + value, 0) / responseTimesMs.length)
194
+ : 0;
195
+ return {
196
+ id: sessionId || portableBasename(sourceId).replace(/\.jsonl$/iu, ""),
197
+ cwd,
198
+ projectName,
199
+ startTime,
200
+ endTime,
201
+ duration,
202
+ messageCount: userMessages + assistantMessages,
203
+ userMessageCount: userMessages,
204
+ assistantMessageCount: assistantMessages,
205
+ toolCallCount,
206
+ tokenUsage: { input: totalInput, output: totalOutput, cacheRead: totalCacheRead, cacheWrite: totalCacheWrite, total: totalTokens },
207
+ cost: { input: costInput, output: costOutput, cacheRead: costCacheRead, cacheWrite: costCacheWrite, total: totalCost },
208
+ models,
209
+ providers,
210
+ thinkingLevels,
211
+ toolUsage,
212
+ stopReasons,
213
+ toolCallErrors,
214
+ hasError: toolCallErrors > 0,
215
+ rageHits,
216
+ metadata: {
217
+ primaryModel,
218
+ responseTimesMs,
219
+ avgResponseTimeMs,
220
+ ...(responseTimesMs[0] === undefined ? {} : { firstResponseTimeMs: responseTimesMs[0] }),
221
+ activityByHour,
222
+ filesMentioned: Array.from(filesMentioned).sort(),
223
+ languageCounts,
224
+ gitActivity,
225
+ toolErrorsByName,
226
+ userInterruptions,
227
+ },
228
+ };
229
+ }
230
+ catch {
231
+ return null;
232
+ }
233
+ }
234
+ function portableBasename(value) {
235
+ return value.replace(/[\\/]+$/u, "").split(/[\\/]/u).pop() || value;
236
+ }
237
+ function collectToolSignals(toolName, inputs, filesMentioned, languageCounts, gitActivity) {
238
+ for (const input of inputs) {
239
+ for (const filePath of extractFilePaths(input)) {
240
+ filesMentioned.add(filePath);
241
+ const language = languageForPath(filePath);
242
+ if (language)
243
+ languageCounts[language] = (languageCounts[language] ?? 0) + 1;
244
+ }
245
+ if (toolName.toLowerCase() === "bash") {
246
+ const command = extractCommand(input);
247
+ if (command)
248
+ recordGitActivity(command, gitActivity);
249
+ }
250
+ }
251
+ }
252
+ function extractFilePaths(value, key = "") {
253
+ if (typeof value === "string") {
254
+ return isPathKey(key) ? normalizeFilePath(value) : [];
255
+ }
256
+ if (Array.isArray(value)) {
257
+ return value.flatMap(item => extractFilePaths(item, key));
258
+ }
259
+ if (!value || typeof value !== "object")
260
+ return [];
261
+ return Object.entries(value).flatMap(([childKey, childValue]) => {
262
+ if (childKey === "command")
263
+ return [];
264
+ return extractFilePaths(childValue, childKey);
265
+ });
266
+ }
267
+ function extractCommand(value) {
268
+ if (!value || typeof value !== "object")
269
+ return undefined;
270
+ const command = value.command;
271
+ return typeof command === "string" ? command : undefined;
272
+ }
273
+ function normalizeFilePath(value) {
274
+ if (value.includes("\n") || value.length > 500)
275
+ return [];
276
+ const trimmed = value.trim();
277
+ if (!trimmed || !path.extname(trimmed))
278
+ return [];
279
+ return [trimmed];
280
+ }
281
+ function isPathKey(key) {
282
+ return /^(path|file|files|filePath|file_path|notebook_path|outputPath|output_path)$/i.test(key);
283
+ }
284
+ function languageForPath(filePath) {
285
+ return LANGUAGE_BY_EXTENSION[path.extname(filePath).toLowerCase()];
286
+ }
287
+ function recordGitActivity(command, gitActivity) {
288
+ if (/\bgit\s+commit\b/.test(command))
289
+ gitActivity.commits++;
290
+ if (/\bgit\s+push\b/.test(command))
291
+ gitActivity.pushes++;
292
+ if (/\bgit\s+status\b/.test(command))
293
+ gitActivity.statusChecks++;
294
+ if (/\bgit\s+diff\b/.test(command))
295
+ gitActivity.diffs++;
296
+ }
297
+ function recordToolError(toolErrorsByName, toolName) {
298
+ const key = toolName || "unknown";
299
+ toolErrorsByName[key] = (toolErrorsByName[key] ?? 0) + 1;
300
+ }
301
+ function getPrimaryModel(models, fallback) {
302
+ const [primary] = Object.entries(models).sort(([, a], [, b]) => {
303
+ if (b.tokens !== a.tokens)
304
+ return b.tokens - a.tokens;
305
+ return b.count - a.count;
306
+ });
307
+ return primary?.[0] ?? fallback;
308
+ }
309
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
package/dist/rage.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export interface RageWordEntry {
2
+ word: string;
3
+ group: string;
4
+ }
5
+ export interface RageMatch {
6
+ word: string;
7
+ group: string;
8
+ }
9
+ export declare const RAGE_WORDLIST: RageWordEntry[];
10
+ export declare function detectRage(text: string): RageMatch[];
11
+ export declare function wordCount(): number;
12
+ //# sourceMappingURL=rage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rage.d.ts","sourceRoot":"","sources":["../src/rage.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,aAAa,EAAE,aAAa,EAmBxC,CAAC;AAWF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,CAOpD;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC"}
package/dist/rage.js ADDED
@@ -0,0 +1,35 @@
1
+ export const RAGE_WORDLIST = [
2
+ { word: "fuck", group: "fuck" }, { word: "fucking", group: "fuck" },
3
+ { word: "fucked", group: "fuck" }, { word: "fucker", group: "fuck" },
4
+ { word: "motherfucker", group: "fuck" }, { word: "clusterfuck", group: "fuck" },
5
+ { word: "fuckup", group: "fuck" }, { word: "bullshit", group: "shit" },
6
+ { word: "shit", group: "shit" }, { word: "shitty", group: "shit" },
7
+ { word: "shithead", group: "shit" }, { word: "shithole", group: "shit" },
8
+ { word: "asshole", group: "ass" }, { word: "jackass", group: "ass" },
9
+ { word: "dumbass", group: "ass" }, { word: "ass", group: "ass" },
10
+ { word: "goddamn", group: "damn" }, { word: "goddammit", group: "damn" },
11
+ { word: "dammit", group: "damn" }, { word: "damn", group: "damn" },
12
+ { word: "bitches", group: "bitch" }, { word: "bitch", group: "bitch" },
13
+ { word: "bastard", group: "bastard" },
14
+ { word: "pissed", group: "piss" }, { word: "piss", group: "piss" },
15
+ { word: "dickhead", group: "dick" }, { word: "dick", group: "dick" },
16
+ { word: "crappy", group: "crap" }, { word: "crap", group: "crap" },
17
+ { word: "hell", group: "hell" },
18
+ { word: "wtf", group: "wtf" }, { word: "stfu", group: "stfu" },
19
+ { word: "cunt", group: "cunt" },
20
+ ];
21
+ const PATTERN = new RegExp(`\\b(${RAGE_WORDLIST.map(w => w.word).join("|")})\\b`, "gi");
22
+ const WORD_MAP = new Map(RAGE_WORDLIST.map(w => [w.word.toLowerCase(), w.group]));
23
+ export function detectRage(text) {
24
+ const hits = [];
25
+ for (const m of text.toLowerCase().matchAll(PATTERN)) {
26
+ const group = WORD_MAP.get(m[0]);
27
+ if (group)
28
+ hits.push({ word: m[0], group });
29
+ }
30
+ return hits;
31
+ }
32
+ export function wordCount() {
33
+ return RAGE_WORDLIST.length;
34
+ }
35
+ //# sourceMappingURL=rage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rage.js","sourceRoot":"","sources":["../src/rage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const FELAN_LOGO = "<?xml version=\"1.0\"?>\n<svg version=\"1.0\" xmlns=\"http://www.w3.org/2000/svg\" width=\"250.000000pt\" height=\"258.000000pt\" viewBox=\"0 0 250.000000 258.000000\" preserveAspectRatio=\"xMidYMid meet\">\n<g transform=\"translate(0.000000,258.000000) scale(0.100000,-0.100000)\" fill=\"#255F44\" stroke=\"none\">\n<path d=\"M1116 2399 c-77 -11 -191 -43 -268 -74 -60 -24 -214 -110 -222 -124&#xA;-3 -4 13 -29 35 -56 56 -70 84 -166 75 -256 l-6 -69 62 51 c131 106 282 160&#xA;453 162 119 1 196 -17 310 -72 378 -183 516 -645 303 -1013 -75 -130 -209&#xA;-247 -347 -303 -411 -167 -883 92 -967 531 -26 137 -12 298 36 410 11 25 20&#xA;47 20 49 0 1 -28 -9 -62 -23 -78 -33 -197 -36 -268 -8 -25 9 -51 18 -59 19&#xA;-36 5 -68 -252 -52 -410 84 -820 1016 -1271 1695 -819 329 219 518 623 476&#xA;1017 -48 450 -323 809 -723 944 -145 48 -340 66 -491 44z\"></path>\n<path d=\"M285 2156 c-89 -41 -135 -115 -135 -213 1 -181 197 -290 350 -195&#xA;119 74 144 244 52 354 -35 41 -116 78 -172 78 -26 0 -66 -10 -95 -24z\"></path>\n<path d=\"M1160 1601 c-83 -25 -156 -98 -190 -187 -72 -192 71 -396 279 -396&#xA;312 0 403 435 118 568 -54 25 -151 32 -207 15z\"></path>\n</g>\n</svg>";
2
+ //# sourceMappingURL=logo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logo.d.ts","sourceRoot":"","sources":["../../src/report-app/logo.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,woCAA8mC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export const FELAN_LOGO = '<?xml version="1.0"?>\n<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="250.000000pt" height="258.000000pt" viewBox="0 0 250.000000 258.000000" preserveAspectRatio="xMidYMid meet">\n<g transform="translate(0.000000,258.000000) scale(0.100000,-0.100000)" fill="#255F44" stroke="none">\n<path d="M1116 2399 c-77 -11 -191 -43 -268 -74 -60 -24 -214 -110 -222 -124&#xA;-3 -4 13 -29 35 -56 56 -70 84 -166 75 -256 l-6 -69 62 51 c131 106 282 160&#xA;453 162 119 1 196 -17 310 -72 378 -183 516 -645 303 -1013 -75 -130 -209&#xA;-247 -347 -303 -411 -167 -883 92 -967 531 -26 137 -12 298 36 410 11 25 20&#xA;47 20 49 0 1 -28 -9 -62 -23 -78 -33 -197 -36 -268 -8 -25 9 -51 18 -59 19&#xA;-36 5 -68 -252 -52 -410 84 -820 1016 -1271 1695 -819 329 219 518 623 476&#xA;1017 -48 450 -323 809 -723 944 -145 48 -340 66 -491 44z"></path>\n<path d="M285 2156 c-89 -41 -135 -115 -135 -213 1 -181 197 -290 350 -195&#xA;119 74 144 244 52 354 -35 41 -116 78 -172 78 -26 0 -66 -10 -95 -24z"></path>\n<path d="M1160 1601 c-83 -25 -156 -98 -190 -187 -72 -192 71 -396 279 -396&#xA;312 0 403 435 118 568 -54 25 -151 32 -207 15z"></path>\n</g>\n</svg>';
2
+ //# sourceMappingURL=logo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logo.js","sourceRoot":"","sources":["../../src/report-app/logo.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,2mCAA2mC,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare const formatNumber: (n: number) => string;
2
+ export declare const formatInteger: (n: number) => string;
3
+ export declare const formatDuration: (m: number) => string;
4
+ export declare const formatCost: (c: number) => string;
5
+ export declare const formatPercent: (ratio: number, maximumFractionDigits?: number) => string;
6
+ export declare const COLORS: string[];
7
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/report-app/utils.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,YAAY,GAAI,GAAG,MAAM,KAAG,MAIxC,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,GAAG,MAAM,KAAG,MAGzC,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,GAAG,MAAM,KAAG,MAI1C,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,GAAG,MAAM,KAAG,MAWtC,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,EAAE,8BAAyB,KAAG,MAMxE,CAAC;AAEF,eAAO,MAAM,MAAM,UAMlB,CAAC"}
@@ -0,0 +1,60 @@
1
+ const compactNumber = new Intl.NumberFormat('en-US', {
2
+ notation: 'compact',
3
+ maximumFractionDigits: 1,
4
+ });
5
+ const regularNumber = new Intl.NumberFormat('en-US', {
6
+ maximumFractionDigits: 2,
7
+ });
8
+ const integerNumber = new Intl.NumberFormat('en-US', {
9
+ maximumFractionDigits: 0,
10
+ });
11
+ export const formatNumber = (n) => {
12
+ if (!Number.isFinite(n))
13
+ return '—';
14
+ if (Math.abs(n) >= 1000)
15
+ return compactNumber.format(n);
16
+ return regularNumber.format(n);
17
+ };
18
+ export const formatInteger = (n) => {
19
+ if (!Number.isFinite(n))
20
+ return '—';
21
+ return integerNumber.format(n);
22
+ };
23
+ export const formatDuration = (m) => {
24
+ if (!Number.isFinite(m))
25
+ return '—';
26
+ if (m >= 60)
27
+ return formatInteger(m / 60) + 'h';
28
+ return formatNumber(m) + 'm';
29
+ };
30
+ export const formatCost = (c) => {
31
+ if (!Number.isFinite(c))
32
+ return '—';
33
+ if (c === 0)
34
+ return '$0.00';
35
+ const absolute = Math.abs(c);
36
+ const sign = c < 0 ? '−' : '';
37
+ if (absolute < 0.000001)
38
+ return `${sign}< $0.000001`;
39
+ const digits = absolute >= 1 ? 2 : absolute >= 0.01 ? 3 : 6;
40
+ return sign + '$' + new Intl.NumberFormat('en-US', {
41
+ minimumFractionDigits: digits,
42
+ maximumFractionDigits: digits,
43
+ }).format(absolute);
44
+ };
45
+ export const formatPercent = (ratio, maximumFractionDigits = 1) => {
46
+ if (!Number.isFinite(ratio))
47
+ return '—';
48
+ return new Intl.NumberFormat('en-US', {
49
+ style: 'percent',
50
+ maximumFractionDigits,
51
+ }).format(ratio);
52
+ };
53
+ export const COLORS = [
54
+ 'hsl(var(--chart-1))',
55
+ 'hsl(var(--chart-2))',
56
+ 'hsl(var(--chart-3))',
57
+ 'hsl(var(--chart-4))',
58
+ 'hsl(var(--chart-5))',
59
+ ];
60
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/report-app/utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Analytics } from './types.js';
2
+ export declare function renderReport(analytics: Analytics): string;
3
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAK5C,wBAAgB,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAGzD"}
package/dist/report.js ADDED
@@ -0,0 +1,7 @@
1
+ import { REPORT_APP_SCRIPT, REPORT_APP_STYLE, REPORT_FAVICON } from './generated/report-app.js';
2
+ const themeBootstrap = `(()=>{const key='felan-insights-theme';let theme;try{theme=localStorage.getItem(key)}catch{}if(theme!=='light'&&theme!=='dark')theme=matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';document.documentElement.dataset.theme=theme})()`;
3
+ export function renderReport(analytics) {
4
+ const data = JSON.stringify(analytics).replace(/</gu, '\\u003c').replace(/>/gu, '\\u003e').replace(/&/gu, '\\u0026');
5
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="color-scheme" content="light dark"><meta name="theme-color" content="#255f44"><link rel="icon" type="image/svg+xml" href="${REPORT_FAVICON}"><title>Felan Insights</title><style>${REPORT_APP_STYLE}</style><script>${themeBootstrap}</script></head><body><div id="root"></div><script>window.__FELAN_INSIGHTS_DATA__=${data};</script><script>${REPORT_APP_SCRIPT.replace(/<\//gu, '<\\/')}</script></body></html>`;
6
+ }
7
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEhG,MAAM,cAAc,GAAG,yPAAyP,CAAC;AAEjR,MAAM,UAAU,YAAY,CAAC,SAAoB;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACrH,OAAO,uQAAuQ,cAAc,yCAAyC,gBAAgB,mBAAmB,cAAc,qFAAqF,IAAI,qBAAqB,iBAAiB,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,yBAAyB,CAAC;AAC1iB,CAAC"}