@code-insights/cli 3.0.2 → 3.0.3

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 (119) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dashboard-dist/index.html +1 -1
  3. package/dist/index.js +3 -1
  4. package/dist/index.js.map +1 -1
  5. package/package.json +1 -1
  6. package/dashboard-dist/assets/index-CuCBzQyQ.js +0 -548
  7. package/dashboard-dist/dist/assets/index-BMhL7wL8.css +0 -1
  8. package/dashboard-dist/dist/assets/index-CuCBzQyQ.js +0 -548
  9. package/dashboard-dist/dist/favicon.svg +0 -4
  10. package/dashboard-dist/dist/index.html +0 -33
  11. package/dist/commands/connect.d.ts +0 -5
  12. package/dist/commands/connect.d.ts.map +0 -1
  13. package/dist/commands/connect.js +0 -39
  14. package/dist/commands/connect.js.map +0 -1
  15. package/dist/commands/insights.d.ts +0 -13
  16. package/dist/commands/insights.d.ts.map +0 -1
  17. package/dist/commands/insights.js +0 -87
  18. package/dist/commands/insights.js.map +0 -1
  19. package/dist/commands/link.d.ts +0 -8
  20. package/dist/commands/link.d.ts.map +0 -1
  21. package/dist/commands/link.js +0 -39
  22. package/dist/commands/link.js.map +0 -1
  23. package/dist/commands/stats/data/cache.d.ts +0 -29
  24. package/dist/commands/stats/data/cache.d.ts.map +0 -1
  25. package/dist/commands/stats/data/cache.js +0 -197
  26. package/dist/commands/stats/data/cache.js.map +0 -1
  27. package/dist/commands/stats/data/firestore.d.ts +0 -13
  28. package/dist/commands/stats/data/firestore.d.ts.map +0 -1
  29. package/dist/commands/stats/data/firestore.js +0 -170
  30. package/dist/commands/stats/data/firestore.js.map +0 -1
  31. package/dist/firebase/client.d.ts +0 -45
  32. package/dist/firebase/client.d.ts.map +0 -1
  33. package/dist/firebase/client.js +0 -344
  34. package/dist/firebase/client.js.map +0 -1
  35. package/dist/parser/insights.d.ts +0 -7
  36. package/dist/parser/insights.d.ts.map +0 -1
  37. package/dist/parser/insights.js +0 -271
  38. package/dist/parser/insights.js.map +0 -1
  39. package/dist/utils/firebase-json.d.ts +0 -87
  40. package/dist/utils/firebase-json.d.ts.map +0 -1
  41. package/dist/utils/firebase-json.js +0 -207
  42. package/dist/utils/firebase-json.js.map +0 -1
  43. package/server-dist/dist/index.d.ts +0 -12
  44. package/server-dist/dist/index.d.ts.map +0 -1
  45. package/server-dist/dist/index.js +0 -92
  46. package/server-dist/dist/index.js.map +0 -1
  47. package/server-dist/dist/llm/analysis.d.ts +0 -80
  48. package/server-dist/dist/llm/analysis.d.ts.map +0 -1
  49. package/server-dist/dist/llm/analysis.js +0 -509
  50. package/server-dist/dist/llm/analysis.js.map +0 -1
  51. package/server-dist/dist/llm/client.d.ts +0 -27
  52. package/server-dist/dist/llm/client.d.ts.map +0 -1
  53. package/server-dist/dist/llm/client.js +0 -71
  54. package/server-dist/dist/llm/client.js.map +0 -1
  55. package/server-dist/dist/llm/index.d.ts +0 -7
  56. package/server-dist/dist/llm/index.d.ts.map +0 -1
  57. package/server-dist/dist/llm/index.js +0 -5
  58. package/server-dist/dist/llm/index.js.map +0 -1
  59. package/server-dist/dist/llm/prompts.d.ts +0 -73
  60. package/server-dist/dist/llm/prompts.d.ts.map +0 -1
  61. package/server-dist/dist/llm/prompts.js +0 -242
  62. package/server-dist/dist/llm/prompts.js.map +0 -1
  63. package/server-dist/dist/llm/providers/anthropic.d.ts +0 -3
  64. package/server-dist/dist/llm/providers/anthropic.d.ts.map +0 -1
  65. package/server-dist/dist/llm/providers/anthropic.js +0 -45
  66. package/server-dist/dist/llm/providers/anthropic.js.map +0 -1
  67. package/server-dist/dist/llm/providers/gemini.d.ts +0 -3
  68. package/server-dist/dist/llm/providers/gemini.d.ts.map +0 -1
  69. package/server-dist/dist/llm/providers/gemini.js +0 -51
  70. package/server-dist/dist/llm/providers/gemini.js.map +0 -1
  71. package/server-dist/dist/llm/providers/ollama.d.ts +0 -12
  72. package/server-dist/dist/llm/providers/ollama.d.ts.map +0 -1
  73. package/server-dist/dist/llm/providers/ollama.js +0 -61
  74. package/server-dist/dist/llm/providers/ollama.js.map +0 -1
  75. package/server-dist/dist/llm/providers/openai.d.ts +0 -3
  76. package/server-dist/dist/llm/providers/openai.d.ts.map +0 -1
  77. package/server-dist/dist/llm/providers/openai.js +0 -39
  78. package/server-dist/dist/llm/providers/openai.js.map +0 -1
  79. package/server-dist/dist/llm/types.d.ts +0 -22
  80. package/server-dist/dist/llm/types.d.ts.map +0 -1
  81. package/server-dist/dist/llm/types.js +0 -5
  82. package/server-dist/dist/llm/types.js.map +0 -1
  83. package/server-dist/dist/routes/analysis.d.ts +0 -4
  84. package/server-dist/dist/routes/analysis.d.ts.map +0 -1
  85. package/server-dist/dist/routes/analysis.js +0 -103
  86. package/server-dist/dist/routes/analysis.js.map +0 -1
  87. package/server-dist/dist/routes/analytics.d.ts +0 -4
  88. package/server-dist/dist/routes/analytics.d.ts.map +0 -1
  89. package/server-dist/dist/routes/analytics.js +0 -47
  90. package/server-dist/dist/routes/analytics.js.map +0 -1
  91. package/server-dist/dist/routes/config.d.ts +0 -4
  92. package/server-dist/dist/routes/config.d.ts.map +0 -1
  93. package/server-dist/dist/routes/config.js +0 -108
  94. package/server-dist/dist/routes/config.js.map +0 -1
  95. package/server-dist/dist/routes/export.d.ts +0 -4
  96. package/server-dist/dist/routes/export.d.ts.map +0 -1
  97. package/server-dist/dist/routes/export.js +0 -52
  98. package/server-dist/dist/routes/export.js.map +0 -1
  99. package/server-dist/dist/routes/insights.d.ts +0 -4
  100. package/server-dist/dist/routes/insights.d.ts.map +0 -1
  101. package/server-dist/dist/routes/insights.js +0 -80
  102. package/server-dist/dist/routes/insights.js.map +0 -1
  103. package/server-dist/dist/routes/messages.d.ts +0 -4
  104. package/server-dist/dist/routes/messages.d.ts.map +0 -1
  105. package/server-dist/dist/routes/messages.js +0 -19
  106. package/server-dist/dist/routes/messages.js.map +0 -1
  107. package/server-dist/dist/routes/projects.d.ts +0 -4
  108. package/server-dist/dist/routes/projects.d.ts.map +0 -1
  109. package/server-dist/dist/routes/projects.js +0 -32
  110. package/server-dist/dist/routes/projects.js.map +0 -1
  111. package/server-dist/dist/routes/sessions.d.ts +0 -4
  112. package/server-dist/dist/routes/sessions.d.ts.map +0 -1
  113. package/server-dist/dist/routes/sessions.js +0 -65
  114. package/server-dist/dist/routes/sessions.js.map +0 -1
  115. package/server-dist/dist/utils.d.ts +0 -6
  116. package/server-dist/dist/utils.d.ts.map +0 -1
  117. package/server-dist/dist/utils.js +0 -9
  118. package/server-dist/dist/utils.js.map +0 -1
  119. /package/dashboard-dist/{dist/assets → assets}/index-CUWKxcRo.js +0 -0
@@ -1,271 +0,0 @@
1
- import { v4 as uuidv4 } from 'uuid';
2
- export function parseInsightContent(raw) {
3
- const isClaudeInsight = raw.includes('★ Insight') || raw.includes('★Insight');
4
- if (isClaudeInsight) {
5
- return parseClaudeFormattedInsight(raw);
6
- }
7
- return parseGenericContent(raw);
8
- }
9
- function parseClaudeFormattedInsight(raw) {
10
- let cleaned = raw.replace(/★\s*Insight\s*─*/g, '').replace(/─+/g, '').replace(/\*\*/g, '').trim();
11
- const lines = cleaned.split('\n').map(l => l.trim()).filter(l => l);
12
- const title = (lines[0] || '').replace(/:$/, '').trim();
13
- const bullets = lines.slice(1).filter(l => l.startsWith('-')).map(l => l.replace(/^-\s*/, '').trim());
14
- const summary = bullets.length > 0 ? `${title}: ${bullets[0]}` : title;
15
- return { title, summary, bullets, rawContent: raw };
16
- }
17
- function parseGenericContent(raw) {
18
- let cleaned = raw.replace(/\*\*/g, '').replace(/\\"/g, '"').replace(/\\n/g, '\n').trim();
19
- const lines = cleaned.split('\n').map(l => l.trim()).filter(l => l);
20
- const title = truncate(lines[0] || cleaned, 100);
21
- const bullets = lines.slice(1).filter(l => l.startsWith('-') || l.startsWith('•')).map(l => l.replace(/^[-•]\s*/, '').trim());
22
- return { title, summary: title, bullets, rawContent: raw };
23
- }
24
- // Pattern matching rules for different insight types
25
- const DECISION_PATTERNS = [
26
- /decided to (.+)/i,
27
- /chose (.+) over (.+)/i,
28
- /went with (.+) because (.+)/i,
29
- /trade-off:?\s*(.+)/i,
30
- /approach:?\s*(.+)/i,
31
- /\*\*decision\*\*:?\s*(.+)/i,
32
- /we('ll| will) use (.+) (for|to|because)/i,
33
- /let's go with (.+)/i,
34
- /the (best|right|better) (approach|solution|choice) is (.+)/i,
35
- ];
36
- const LEARNING_PATTERNS = [
37
- /learned that (.+)/i,
38
- /TIL:?\s*(.+)/i,
39
- /insight:?\s*(.+)/i,
40
- /realized (.+)/i,
41
- /mistake:?\s*(.+)/i,
42
- /note to self:?\s*(.+)/i,
43
- /important:?\s*(.+)/i,
44
- /remember:?\s*(.+)/i,
45
- /turns out (.+)/i,
46
- /didn't know (.+)/i,
47
- ];
48
- const WORKITEM_SIGNALS = {
49
- feature: ['added', 'implemented', 'created', 'built', 'new feature', 'introducing'],
50
- bugfix: ['fixed', 'resolved', 'patched', 'corrected', 'bug fix', 'fixing'],
51
- refactor: ['refactored', 'restructured', 'reorganized', 'cleaned', 'improved', 'simplified'],
52
- docs: ['documented', 'documentation', 'readme', 'comments', 'jsdoc'],
53
- test: ['tested', 'test', 'spec', 'coverage', 'unit test', 'integration test'],
54
- };
55
- const WORK_TOOLS = ['Edit', 'Write', 'Bash'];
56
- /**
57
- * Extract insights from a parsed session using pattern matching
58
- */
59
- export function extractInsights(session) {
60
- const insights = [];
61
- const projectId = generateProjectId(session.projectPath);
62
- // Extract from assistant messages
63
- for (const message of session.messages) {
64
- if (message.type === 'assistant') {
65
- // Check for decisions
66
- const decisions = extractDecisions(message, session, projectId);
67
- insights.push(...decisions);
68
- // Check for learnings
69
- const learnings = extractLearnings(message, session, projectId);
70
- insights.push(...learnings);
71
- // Check for work items from tool calls
72
- const workItems = extractWorkItems(message, session, projectId);
73
- insights.push(...workItems);
74
- }
75
- }
76
- // Add effort insight for the session
77
- const effortInsight = createEffortInsight(session, projectId);
78
- if (effortInsight) {
79
- insights.push(effortInsight);
80
- }
81
- return insights;
82
- }
83
- /**
84
- * Extract decision insights from a message
85
- */
86
- function extractDecisions(message, session, projectId) {
87
- const insights = [];
88
- const content = message.content;
89
- for (const pattern of DECISION_PATTERNS) {
90
- const match = content.match(pattern);
91
- if (match) {
92
- const extractedText = match[1] || match[0];
93
- // Get surrounding context (up to 200 chars)
94
- const matchIndex = content.indexOf(match[0]);
95
- const contextStart = Math.max(0, matchIndex - 100);
96
- const contextEnd = Math.min(content.length, matchIndex + match[0].length + 100);
97
- const context = content.slice(contextStart, contextEnd);
98
- insights.push({
99
- id: uuidv4(),
100
- sessionId: session.id,
101
- projectId,
102
- projectName: session.projectName,
103
- type: 'decision',
104
- title: truncate(extractedText, 100),
105
- content: context,
106
- summary: '',
107
- bullets: [],
108
- confidence: 0.7,
109
- source: 'pattern',
110
- metadata: {
111
- reasoning: extractedText,
112
- },
113
- timestamp: message.timestamp,
114
- });
115
- // Only extract first match per pattern to avoid duplicates
116
- break;
117
- }
118
- }
119
- return insights;
120
- }
121
- /**
122
- * Extract learning insights from a message
123
- */
124
- function extractLearnings(message, session, projectId) {
125
- const insights = [];
126
- const content = message.content;
127
- for (const pattern of LEARNING_PATTERNS) {
128
- const match = content.match(pattern);
129
- if (match) {
130
- const extractedText = match[1] || match[0];
131
- // Get surrounding context
132
- const matchIndex = content.indexOf(match[0]);
133
- const contextStart = Math.max(0, matchIndex - 100);
134
- const contextEnd = Math.min(content.length, matchIndex + match[0].length + 100);
135
- const context = content.slice(contextStart, contextEnd);
136
- insights.push({
137
- id: uuidv4(),
138
- sessionId: session.id,
139
- projectId,
140
- projectName: session.projectName,
141
- type: 'learning',
142
- title: truncate(extractedText, 100),
143
- content: context,
144
- summary: '',
145
- bullets: [],
146
- confidence: 0.6,
147
- source: 'pattern',
148
- metadata: {},
149
- timestamp: message.timestamp,
150
- });
151
- break;
152
- }
153
- }
154
- return insights;
155
- }
156
- /**
157
- * Extract work item insights from tool calls
158
- */
159
- function extractWorkItems(message, session, projectId) {
160
- const insights = [];
161
- // Check for file-modifying tool calls
162
- const fileEdits = message.toolCalls.filter((tc) => WORK_TOOLS.includes(tc.name));
163
- if (fileEdits.length === 0) {
164
- return insights;
165
- }
166
- // Extract files modified
167
- const files = [];
168
- for (const tc of fileEdits) {
169
- if (tc.name === 'Edit' || tc.name === 'Write') {
170
- const filePath = tc.input.file_path;
171
- if (filePath) {
172
- files.push(filePath);
173
- }
174
- }
175
- }
176
- if (files.length === 0) {
177
- return insights;
178
- }
179
- // Determine work type from message content
180
- const workType = determineWorkType(message.content);
181
- // Create a consolidated work item for this message
182
- insights.push({
183
- id: uuidv4(),
184
- sessionId: session.id,
185
- projectId,
186
- projectName: session.projectName,
187
- type: 'workitem',
188
- title: `${capitalizeFirst(workType)}: ${files.length} file(s) modified`,
189
- content: `Files: ${files.join(', ')}`,
190
- summary: '',
191
- bullets: [],
192
- confidence: 0.9,
193
- source: 'pattern',
194
- metadata: {
195
- files,
196
- workType,
197
- },
198
- timestamp: message.timestamp,
199
- });
200
- return insights;
201
- }
202
- /**
203
- * Create an effort insight for the session
204
- */
205
- function createEffortInsight(session, projectId) {
206
- // Calculate session duration in minutes
207
- const durationMs = session.endedAt.getTime() - session.startedAt.getTime();
208
- const durationMinutes = Math.round(durationMs / 60000);
209
- if (durationMinutes < 1) {
210
- return null;
211
- }
212
- return {
213
- id: uuidv4(),
214
- sessionId: session.id,
215
- projectId,
216
- projectName: session.projectName,
217
- type: 'effort',
218
- title: `Session: ${durationMinutes} min, ${session.messageCount} messages`,
219
- content: `User: ${session.userMessageCount} messages, Assistant: ${session.assistantMessageCount} messages, Tool calls: ${session.toolCallCount}`,
220
- summary: '',
221
- bullets: [],
222
- confidence: 1.0,
223
- source: 'pattern',
224
- metadata: {
225
- duration: durationMinutes,
226
- },
227
- timestamp: session.startedAt,
228
- };
229
- }
230
- /**
231
- * Determine work type from message content
232
- */
233
- function determineWorkType(content) {
234
- const lowerContent = content.toLowerCase();
235
- for (const [workType, signals] of Object.entries(WORKITEM_SIGNALS)) {
236
- for (const signal of signals) {
237
- if (lowerContent.includes(signal)) {
238
- return workType;
239
- }
240
- }
241
- }
242
- return 'feature'; // Default
243
- }
244
- /**
245
- * Generate a stable project ID from path
246
- */
247
- function generateProjectId(projectPath) {
248
- // Create a simple hash from the path
249
- let hash = 0;
250
- for (let i = 0; i < projectPath.length; i++) {
251
- const char = projectPath.charCodeAt(i);
252
- hash = (hash << 5) - hash + char;
253
- hash = hash & hash;
254
- }
255
- return `proj_${Math.abs(hash).toString(16)}`;
256
- }
257
- /**
258
- * Truncate string to max length
259
- */
260
- function truncate(str, maxLength) {
261
- if (str.length <= maxLength)
262
- return str;
263
- return str.slice(0, maxLength - 3) + '...';
264
- }
265
- /**
266
- * Capitalize first letter
267
- */
268
- function capitalizeFirst(str) {
269
- return str.charAt(0).toUpperCase() + str.slice(1);
270
- }
271
- //# sourceMappingURL=insights.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"insights.js","sourceRoot":"","sources":["../../src/parser/insights.ts"],"names":[],"mappings":"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"}
@@ -1,87 +0,0 @@
1
- import type { FirebaseServiceAccountJson, FirebaseWebConfig } from '../types.js';
2
- export type FileReadResult<T> = {
3
- success: true;
4
- data: T;
5
- } | {
6
- success: false;
7
- error: 'not_found' | 'invalid_json' | 'permission_denied' | 'unknown';
8
- message: string;
9
- };
10
- /**
11
- * Validate Firebase Service Account JSON structure
12
- */
13
- export declare function validateServiceAccountJson(data: unknown): data is FirebaseServiceAccountJson;
14
- /**
15
- * Check if data looks like a service account (for cross-type detection)
16
- */
17
- export declare function looksLikeServiceAccount(data: unknown): boolean;
18
- /**
19
- * Check if data looks like a web config (for cross-type detection)
20
- */
21
- export declare function looksLikeWebConfig(data: unknown): boolean;
22
- /**
23
- * Validate Firebase Web SDK config structure
24
- */
25
- export declare function validateWebConfig(data: unknown): data is FirebaseWebConfig;
26
- /**
27
- * Parse Firebase's JavaScript config snippet into a JSON object.
28
- *
29
- * Firebase Console gives you JavaScript like:
30
- * const firebaseConfig = {
31
- * apiKey: "AIza...",
32
- * authDomain: "my-project.firebaseapp.com",
33
- * ...
34
- * };
35
- *
36
- * This function extracts the object and converts it to a parsed object.
37
- */
38
- export declare function parseFirebaseJsConfig(content: string): Record<string, unknown> | null;
39
- /**
40
- * Read a Firebase config file — accepts JSON or JavaScript format.
41
- *
42
- * Tries JSON.parse first. If that fails, tries to extract a JS object
43
- * literal (handles the raw Firebase Console snippet).
44
- */
45
- export declare function readFirebaseConfigFile<T>(filePath: string): FileReadResult<T>;
46
- /**
47
- * Resolve file path (expand ~ to home directory)
48
- */
49
- export declare function resolveFilePath(filePath: string): string;
50
- /**
51
- * Check if file exists
52
- */
53
- export declare function fileExists(filePath: string): boolean;
54
- /**
55
- * Read and parse a JSON file with detailed error reporting
56
- */
57
- export declare function readJsonFileWithError<T>(filePath: string): FileReadResult<T>;
58
- /**
59
- * Read and parse a JSON file (simple version, returns null on error)
60
- */
61
- export declare function readJsonFile<T>(filePath: string): T | null;
62
- /**
63
- * Extract service account config from JSON file
64
- */
65
- export declare function extractServiceAccountConfig(json: FirebaseServiceAccountJson): {
66
- projectId: string;
67
- clientEmail: string;
68
- privateKey: string;
69
- };
70
- /**
71
- * Encode web config for URL parameter (base64url encoding per RFC 4648)
72
- *
73
- * The web app decodes this with:
74
- * const base64 = encoded.replace(/-/g, '+').replace(/_/g, '/');
75
- * const json = atob(base64);
76
- * const config = JSON.parse(json);
77
- */
78
- export declare function encodeWebConfigForUrl(config: FirebaseWebConfig): string;
79
- /**
80
- * Generate the web dashboard URL with embedded config
81
- *
82
- * Note: Firebase web API keys are designed for client-side use and are
83
- * restricted by Firestore security rules, not by key secrecy. However,
84
- * users should still avoid sharing this URL publicly.
85
- */
86
- export declare function generateDashboardUrl(config: FirebaseWebConfig): string;
87
- //# sourceMappingURL=firebase-json.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"firebase-json.d.ts","sourceRoot":"","sources":["../../src/utils/firebase-json.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEjF,MAAM,MAAM,cAAc,CAAC,CAAC,IACxB;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,GAC1B;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,WAAW,GAAG,cAAc,GAAG,mBAAmB,GAAG,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/G;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,0BAA0B,CAY5F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAI9D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAIzD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,iBAAiB,CAa1E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAkCrF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,CAmC7E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGpD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,CAoB5E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAG1D;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,0BAA0B;;;;EAM3E;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAOvE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAGtE"}
@@ -1,207 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as os from 'os';
3
- /**
4
- * Validate Firebase Service Account JSON structure
5
- */
6
- export function validateServiceAccountJson(data) {
7
- if (!data || typeof data !== 'object')
8
- return false;
9
- const obj = data;
10
- return (obj.type === 'service_account' &&
11
- typeof obj.project_id === 'string' &&
12
- typeof obj.private_key === 'string' &&
13
- typeof obj.client_email === 'string' &&
14
- obj.private_key.includes('-----BEGIN PRIVATE KEY-----'));
15
- }
16
- /**
17
- * Check if data looks like a service account (for cross-type detection)
18
- */
19
- export function looksLikeServiceAccount(data) {
20
- if (!data || typeof data !== 'object')
21
- return false;
22
- const obj = data;
23
- return obj.type === 'service_account' || typeof obj.private_key === 'string';
24
- }
25
- /**
26
- * Check if data looks like a web config (for cross-type detection)
27
- */
28
- export function looksLikeWebConfig(data) {
29
- if (!data || typeof data !== 'object')
30
- return false;
31
- const obj = data;
32
- return typeof obj.apiKey === 'string' || typeof obj.authDomain === 'string';
33
- }
34
- /**
35
- * Validate Firebase Web SDK config structure
36
- */
37
- export function validateWebConfig(data) {
38
- if (!data || typeof data !== 'object')
39
- return false;
40
- const obj = data;
41
- return (typeof obj.apiKey === 'string' &&
42
- typeof obj.authDomain === 'string' &&
43
- typeof obj.projectId === 'string' &&
44
- typeof obj.storageBucket === 'string' &&
45
- typeof obj.messagingSenderId === 'string' &&
46
- typeof obj.appId === 'string');
47
- }
48
- /**
49
- * Parse Firebase's JavaScript config snippet into a JSON object.
50
- *
51
- * Firebase Console gives you JavaScript like:
52
- * const firebaseConfig = {
53
- * apiKey: "AIza...",
54
- * authDomain: "my-project.firebaseapp.com",
55
- * ...
56
- * };
57
- *
58
- * This function extracts the object and converts it to a parsed object.
59
- */
60
- export function parseFirebaseJsConfig(content) {
61
- try {
62
- // Strip single-line comments
63
- let cleaned = content.replace(/\/\/.*$/gm, '');
64
- // Strip multi-line comments
65
- cleaned = cleaned.replace(/\/\*[\s\S]*?\*\//g, '');
66
- // Strip import statements
67
- cleaned = cleaned.replace(/^import\s+.*$/gm, '');
68
- // Strip lines like: const app = initializeApp(firebaseConfig);
69
- cleaned = cleaned.replace(/^.*initializeApp.*$/gm, '');
70
- // Extract the object literal between first { and last }
71
- const firstBrace = cleaned.indexOf('{');
72
- const lastBrace = cleaned.lastIndexOf('}');
73
- if (firstBrace === -1 || lastBrace === -1 || lastBrace <= firstBrace) {
74
- return null;
75
- }
76
- let objectStr = cleaned.substring(firstBrace, lastBrace + 1);
77
- // Quote unquoted keys at start of lines: apiKey: → "apiKey":
78
- // Uses ^ with multiline to avoid matching colons inside string values
79
- objectStr = objectStr.replace(/^(\s*)(\w+)\s*:/gm, '$1"$2":');
80
- // Remove trailing commas before }
81
- objectStr = objectStr.replace(/,\s*}/g, '}');
82
- return JSON.parse(objectStr);
83
- }
84
- catch {
85
- return null;
86
- }
87
- }
88
- /**
89
- * Read a Firebase config file — accepts JSON or JavaScript format.
90
- *
91
- * Tries JSON.parse first. If that fails, tries to extract a JS object
92
- * literal (handles the raw Firebase Console snippet).
93
- */
94
- export function readFirebaseConfigFile(filePath) {
95
- const resolvedPath = resolveFilePath(filePath);
96
- try {
97
- if (!fs.existsSync(resolvedPath)) {
98
- return { success: false, error: 'not_found', message: `File not found: ${filePath}` };
99
- }
100
- const content = fs.readFileSync(resolvedPath, 'utf-8');
101
- // Try JSON first
102
- try {
103
- const data = JSON.parse(content);
104
- return { success: true, data };
105
- }
106
- catch {
107
- // Not valid JSON — try parsing as JavaScript
108
- }
109
- // Try Firebase JS config format
110
- const parsed = parseFirebaseJsConfig(content);
111
- if (parsed) {
112
- return { success: true, data: parsed };
113
- }
114
- return {
115
- success: false,
116
- error: 'invalid_json',
117
- message: 'Could not parse file as JSON or Firebase JavaScript config',
118
- };
119
- }
120
- catch (err) {
121
- if (err instanceof Error && 'code' in err && err.code === 'EACCES') {
122
- return { success: false, error: 'permission_denied', message: 'Permission denied reading file' };
123
- }
124
- return { success: false, error: 'unknown', message: `Error reading file: ${err instanceof Error ? err.message : 'Unknown error'}` };
125
- }
126
- }
127
- /**
128
- * Resolve file path (expand ~ to home directory)
129
- */
130
- export function resolveFilePath(filePath) {
131
- return filePath.replace(/^~/, os.homedir());
132
- }
133
- /**
134
- * Check if file exists
135
- */
136
- export function fileExists(filePath) {
137
- const resolvedPath = resolveFilePath(filePath);
138
- return fs.existsSync(resolvedPath);
139
- }
140
- /**
141
- * Read and parse a JSON file with detailed error reporting
142
- */
143
- export function readJsonFileWithError(filePath) {
144
- const resolvedPath = resolveFilePath(filePath);
145
- try {
146
- if (!fs.existsSync(resolvedPath)) {
147
- return { success: false, error: 'not_found', message: `File not found: ${filePath}` };
148
- }
149
- const content = fs.readFileSync(resolvedPath, 'utf-8');
150
- const data = JSON.parse(content);
151
- return { success: true, data };
152
- }
153
- catch (err) {
154
- if (err instanceof SyntaxError) {
155
- return { success: false, error: 'invalid_json', message: 'File contains invalid JSON' };
156
- }
157
- if (err instanceof Error && 'code' in err && err.code === 'EACCES') {
158
- return { success: false, error: 'permission_denied', message: 'Permission denied reading file' };
159
- }
160
- return { success: false, error: 'unknown', message: `Error reading file: ${err instanceof Error ? err.message : 'Unknown error'}` };
161
- }
162
- }
163
- /**
164
- * Read and parse a JSON file (simple version, returns null on error)
165
- */
166
- export function readJsonFile(filePath) {
167
- const result = readJsonFileWithError(filePath);
168
- return result.success ? result.data : null;
169
- }
170
- /**
171
- * Extract service account config from JSON file
172
- */
173
- export function extractServiceAccountConfig(json) {
174
- return {
175
- projectId: json.project_id,
176
- clientEmail: json.client_email,
177
- privateKey: json.private_key,
178
- };
179
- }
180
- /**
181
- * Encode web config for URL parameter (base64url encoding per RFC 4648)
182
- *
183
- * The web app decodes this with:
184
- * const base64 = encoded.replace(/-/g, '+').replace(/_/g, '/');
185
- * const json = atob(base64);
186
- * const config = JSON.parse(json);
187
- */
188
- export function encodeWebConfigForUrl(config) {
189
- const json = JSON.stringify(config);
190
- return Buffer.from(json, 'utf-8')
191
- .toString('base64')
192
- .replace(/\+/g, '-')
193
- .replace(/\//g, '_')
194
- .replace(/=+$/, '');
195
- }
196
- /**
197
- * Generate the web dashboard URL with embedded config
198
- *
199
- * Note: Firebase web API keys are designed for client-side use and are
200
- * restricted by Firestore security rules, not by key secrecy. However,
201
- * users should still avoid sharing this URL publicly.
202
- */
203
- export function generateDashboardUrl(config) {
204
- const encodedConfig = encodeWebConfigForUrl(config);
205
- return `https://code-insights.app/?config=${encodedConfig}`;
206
- }
207
- //# sourceMappingURL=firebase-json.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"firebase-json.js","sourceRoot":"","sources":["../../src/utils/firebase-json.ts"],"names":[],"mappings":"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"}
@@ -1,12 +0,0 @@
1
- export interface ServerOptions {
2
- port: number;
3
- staticDir: string;
4
- openBrowser: boolean;
5
- }
6
- /**
7
- * Start the Code Insights local dashboard server.
8
- * Serves the Hono API and the pre-built Vite SPA from staticDir.
9
- * Called by the CLI `dashboard` command.
10
- */
11
- export declare function startServer(options: ServerOptions): Promise<void>;
12
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IAEb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAiFvE"}