@code-insights/cli 2.1.0 → 3.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.
- package/CHANGELOG.md +39 -0
- package/README.md +146 -156
- package/dashboard-dist/assets/index-BMhL7wL8.css +1 -0
- package/dashboard-dist/assets/index-CuCBzQyQ.js +548 -0
- package/dashboard-dist/dist/assets/index-BMhL7wL8.css +1 -0
- package/dashboard-dist/dist/assets/index-CuCBzQyQ.js +548 -0
- package/dashboard-dist/dist/favicon.svg +4 -0
- package/dashboard-dist/dist/index.html +33 -0
- package/dashboard-dist/favicon.svg +4 -0
- package/dashboard-dist/index.html +33 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +188 -69
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/dashboard.d.ts +16 -0
- package/dist/commands/dashboard.d.ts.map +1 -0
- package/dist/commands/dashboard.js +82 -0
- package/dist/commands/dashboard.js.map +1 -0
- package/dist/commands/init.d.ts +3 -4
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +24 -201
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install-hook.d.ts.map +1 -1
- package/dist/commands/install-hook.js +4 -21
- package/dist/commands/install-hook.js.map +1 -1
- package/dist/commands/open.d.ts +2 -1
- package/dist/commands/open.d.ts.map +1 -1
- package/dist/commands/open.js +10 -21
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/reset.d.ts.map +1 -1
- package/dist/commands/reset.js +38 -69
- package/dist/commands/reset.js.map +1 -1
- package/dist/commands/stats/actions/error-handler.d.ts.map +1 -1
- package/dist/commands/stats/actions/error-handler.js +1 -11
- package/dist/commands/stats/actions/error-handler.js.map +1 -1
- package/dist/commands/stats/data/local.d.ts +0 -2
- package/dist/commands/stats/data/local.d.ts.map +1 -1
- package/dist/commands/stats/data/local.js +44 -44
- package/dist/commands/stats/data/local.js.map +1 -1
- package/dist/commands/stats/data/source.d.ts +3 -9
- package/dist/commands/stats/data/source.d.ts.map +1 -1
- package/dist/commands/stats/data/source.js +3 -35
- package/dist/commands/stats/data/source.js.map +1 -1
- package/dist/commands/stats/data/types.d.ts +1 -12
- package/dist/commands/stats/data/types.d.ts.map +1 -1
- package/dist/commands/stats/data/types.js +0 -16
- package/dist/commands/stats/data/types.js.map +1 -1
- package/dist/commands/stats/shared.d.ts.map +1 -1
- package/dist/commands/stats/shared.js +1 -5
- package/dist/commands/stats/shared.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +53 -92
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/sync.d.ts +5 -5
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +31 -39
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/telemetry.d.ts.map +1 -1
- package/dist/commands/telemetry.js +0 -1
- package/dist/commands/telemetry.js.map +1 -1
- package/dist/constants/llm-providers.d.ts +5 -0
- package/dist/constants/llm-providers.d.ts.map +1 -0
- package/dist/constants/llm-providers.js +56 -0
- package/dist/constants/llm-providers.js.map +1 -0
- package/dist/db/client.d.ts +17 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +53 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/migrate.d.ts +9 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +31 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/read.d.ts +42 -0
- package/dist/db/read.d.ts.map +1 -0
- package/dist/db/read.js +194 -0
- package/dist/db/read.js.map +1 -0
- package/dist/db/schema.d.ts +3 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +129 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/write.d.ts +24 -0
- package/dist/db/write.d.ts.map +1 -0
- package/dist/db/write.js +287 -0
- package/dist/db/write.js.map +1 -0
- package/dist/firebase/client.d.ts +5 -0
- package/dist/firebase/client.d.ts.map +1 -1
- package/dist/firebase/client.js +23 -0
- package/dist/firebase/client.js.map +1 -1
- package/dist/index.js +12 -12
- package/dist/index.js.map +1 -1
- package/dist/providers/context.d.ts +3 -0
- package/dist/providers/context.d.ts.map +1 -0
- package/dist/providers/context.js +13 -0
- package/dist/providers/context.js.map +1 -0
- package/dist/providers/copilot.d.ts +18 -0
- package/dist/providers/copilot.d.ts.map +1 -0
- package/dist/providers/copilot.js +289 -0
- package/dist/providers/copilot.js.map +1 -0
- package/dist/providers/cursor.d.ts.map +1 -1
- package/dist/providers/cursor.js +8 -3
- package/dist/providers/cursor.js.map +1 -1
- package/dist/providers/registry.d.ts.map +1 -1
- package/dist/providers/registry.js +3 -0
- package/dist/providers/registry.js.map +1 -1
- package/dist/types.d.ts +38 -47
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/browser.d.ts +6 -0
- package/dist/utils/browser.d.ts.map +1 -0
- package/dist/utils/browser.js +23 -0
- package/dist/utils/browser.js.map +1 -0
- package/dist/utils/config.d.ts +9 -21
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +23 -50
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/telemetry.js +2 -7
- package/dist/utils/telemetry.js.map +1 -1
- package/dist/utils/tips.js +1 -1
- package/dist/utils/tips.js.map +1 -1
- package/package.json +19 -5
- package/server-dist/dist/index.d.ts +12 -0
- package/server-dist/dist/index.d.ts.map +1 -0
- package/server-dist/dist/index.js +92 -0
- package/server-dist/dist/index.js.map +1 -0
- package/server-dist/dist/llm/analysis.d.ts +80 -0
- package/server-dist/dist/llm/analysis.d.ts.map +1 -0
- package/server-dist/dist/llm/analysis.js +509 -0
- package/server-dist/dist/llm/analysis.js.map +1 -0
- package/server-dist/dist/llm/client.d.ts +27 -0
- package/server-dist/dist/llm/client.d.ts.map +1 -0
- package/server-dist/dist/llm/client.js +71 -0
- package/server-dist/dist/llm/client.js.map +1 -0
- package/server-dist/dist/llm/index.d.ts +7 -0
- package/server-dist/dist/llm/index.d.ts.map +1 -0
- package/server-dist/dist/llm/index.js +5 -0
- package/server-dist/dist/llm/index.js.map +1 -0
- package/server-dist/dist/llm/prompts.d.ts +73 -0
- package/server-dist/dist/llm/prompts.d.ts.map +1 -0
- package/server-dist/dist/llm/prompts.js +242 -0
- package/server-dist/dist/llm/prompts.js.map +1 -0
- package/server-dist/dist/llm/providers/anthropic.d.ts +3 -0
- package/server-dist/dist/llm/providers/anthropic.d.ts.map +1 -0
- package/server-dist/dist/llm/providers/anthropic.js +45 -0
- package/server-dist/dist/llm/providers/anthropic.js.map +1 -0
- package/server-dist/dist/llm/providers/gemini.d.ts +3 -0
- package/server-dist/dist/llm/providers/gemini.d.ts.map +1 -0
- package/server-dist/dist/llm/providers/gemini.js +51 -0
- package/server-dist/dist/llm/providers/gemini.js.map +1 -0
- package/server-dist/dist/llm/providers/ollama.d.ts +12 -0
- package/server-dist/dist/llm/providers/ollama.d.ts.map +1 -0
- package/server-dist/dist/llm/providers/ollama.js +61 -0
- package/server-dist/dist/llm/providers/ollama.js.map +1 -0
- package/server-dist/dist/llm/providers/openai.d.ts +3 -0
- package/server-dist/dist/llm/providers/openai.d.ts.map +1 -0
- package/server-dist/dist/llm/providers/openai.js +39 -0
- package/server-dist/dist/llm/providers/openai.js.map +1 -0
- package/server-dist/dist/llm/types.d.ts +22 -0
- package/server-dist/dist/llm/types.d.ts.map +1 -0
- package/server-dist/dist/llm/types.js +5 -0
- package/server-dist/dist/llm/types.js.map +1 -0
- package/server-dist/dist/routes/analysis.d.ts +4 -0
- package/server-dist/dist/routes/analysis.d.ts.map +1 -0
- package/server-dist/dist/routes/analysis.js +103 -0
- package/server-dist/dist/routes/analysis.js.map +1 -0
- package/server-dist/dist/routes/analytics.d.ts +4 -0
- package/server-dist/dist/routes/analytics.d.ts.map +1 -0
- package/server-dist/dist/routes/analytics.js +47 -0
- package/server-dist/dist/routes/analytics.js.map +1 -0
- package/server-dist/dist/routes/config.d.ts +4 -0
- package/server-dist/dist/routes/config.d.ts.map +1 -0
- package/server-dist/dist/routes/config.js +108 -0
- package/server-dist/dist/routes/config.js.map +1 -0
- package/server-dist/dist/routes/export.d.ts +4 -0
- package/server-dist/dist/routes/export.d.ts.map +1 -0
- package/server-dist/dist/routes/export.js +52 -0
- package/server-dist/dist/routes/export.js.map +1 -0
- package/server-dist/dist/routes/insights.d.ts +4 -0
- package/server-dist/dist/routes/insights.d.ts.map +1 -0
- package/server-dist/dist/routes/insights.js +80 -0
- package/server-dist/dist/routes/insights.js.map +1 -0
- package/server-dist/dist/routes/messages.d.ts +4 -0
- package/server-dist/dist/routes/messages.d.ts.map +1 -0
- package/server-dist/dist/routes/messages.js +19 -0
- package/server-dist/dist/routes/messages.js.map +1 -0
- package/server-dist/dist/routes/projects.d.ts +4 -0
- package/server-dist/dist/routes/projects.d.ts.map +1 -0
- package/server-dist/dist/routes/projects.js +32 -0
- package/server-dist/dist/routes/projects.js.map +1 -0
- package/server-dist/dist/routes/sessions.d.ts +4 -0
- package/server-dist/dist/routes/sessions.d.ts.map +1 -0
- package/server-dist/dist/routes/sessions.js +65 -0
- package/server-dist/dist/routes/sessions.js.map +1 -0
- package/server-dist/dist/utils.d.ts +6 -0
- package/server-dist/dist/utils.d.ts.map +1 -0
- package/server-dist/dist/utils.js +9 -0
- package/server-dist/dist/utils.js.map +1 -0
- package/server-dist/index.d.ts +12 -0
- package/server-dist/index.d.ts.map +1 -0
- package/server-dist/index.js +92 -0
- package/server-dist/index.js.map +1 -0
- package/server-dist/llm/analysis.d.ts +80 -0
- package/server-dist/llm/analysis.d.ts.map +1 -0
- package/server-dist/llm/analysis.js +509 -0
- package/server-dist/llm/analysis.js.map +1 -0
- package/server-dist/llm/client.d.ts +27 -0
- package/server-dist/llm/client.d.ts.map +1 -0
- package/server-dist/llm/client.js +71 -0
- package/server-dist/llm/client.js.map +1 -0
- package/server-dist/llm/index.d.ts +7 -0
- package/server-dist/llm/index.d.ts.map +1 -0
- package/server-dist/llm/index.js +5 -0
- package/server-dist/llm/index.js.map +1 -0
- package/server-dist/llm/prompts.d.ts +73 -0
- package/server-dist/llm/prompts.d.ts.map +1 -0
- package/server-dist/llm/prompts.js +242 -0
- package/server-dist/llm/prompts.js.map +1 -0
- package/server-dist/llm/providers/anthropic.d.ts +3 -0
- package/server-dist/llm/providers/anthropic.d.ts.map +1 -0
- package/server-dist/llm/providers/anthropic.js +45 -0
- package/server-dist/llm/providers/anthropic.js.map +1 -0
- package/server-dist/llm/providers/gemini.d.ts +3 -0
- package/server-dist/llm/providers/gemini.d.ts.map +1 -0
- package/server-dist/llm/providers/gemini.js +51 -0
- package/server-dist/llm/providers/gemini.js.map +1 -0
- package/server-dist/llm/providers/ollama.d.ts +12 -0
- package/server-dist/llm/providers/ollama.d.ts.map +1 -0
- package/server-dist/llm/providers/ollama.js +61 -0
- package/server-dist/llm/providers/ollama.js.map +1 -0
- package/server-dist/llm/providers/openai.d.ts +3 -0
- package/server-dist/llm/providers/openai.d.ts.map +1 -0
- package/server-dist/llm/providers/openai.js +39 -0
- package/server-dist/llm/providers/openai.js.map +1 -0
- package/server-dist/llm/types.d.ts +22 -0
- package/server-dist/llm/types.d.ts.map +1 -0
- package/server-dist/llm/types.js +5 -0
- package/server-dist/llm/types.js.map +1 -0
- package/server-dist/routes/analysis.d.ts +4 -0
- package/server-dist/routes/analysis.d.ts.map +1 -0
- package/server-dist/routes/analysis.js +103 -0
- package/server-dist/routes/analysis.js.map +1 -0
- package/server-dist/routes/analytics.d.ts +4 -0
- package/server-dist/routes/analytics.d.ts.map +1 -0
- package/server-dist/routes/analytics.js +47 -0
- package/server-dist/routes/analytics.js.map +1 -0
- package/server-dist/routes/config.d.ts +4 -0
- package/server-dist/routes/config.d.ts.map +1 -0
- package/server-dist/routes/config.js +108 -0
- package/server-dist/routes/config.js.map +1 -0
- package/server-dist/routes/export.d.ts +4 -0
- package/server-dist/routes/export.d.ts.map +1 -0
- package/server-dist/routes/export.js +52 -0
- package/server-dist/routes/export.js.map +1 -0
- package/server-dist/routes/insights.d.ts +4 -0
- package/server-dist/routes/insights.d.ts.map +1 -0
- package/server-dist/routes/insights.js +80 -0
- package/server-dist/routes/insights.js.map +1 -0
- package/server-dist/routes/messages.d.ts +4 -0
- package/server-dist/routes/messages.d.ts.map +1 -0
- package/server-dist/routes/messages.js +19 -0
- package/server-dist/routes/messages.js.map +1 -0
- package/server-dist/routes/projects.d.ts +4 -0
- package/server-dist/routes/projects.d.ts.map +1 -0
- package/server-dist/routes/projects.js +32 -0
- package/server-dist/routes/projects.js.map +1 -0
- package/server-dist/routes/sessions.d.ts +4 -0
- package/server-dist/routes/sessions.d.ts.map +1 -0
- package/server-dist/routes/sessions.js +65 -0
- package/server-dist/routes/sessions.js.map +1 -0
- package/server-dist/utils.d.ts +6 -0
- package/server-dist/utils.d.ts.map +1 -0
- package/server-dist/utils.js +9 -0
- package/server-dist/utils.js.map +1 -0
package/dist/commands/init.js
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
import inquirer from 'inquirer';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import { saveConfig,
|
|
3
|
+
import { saveConfig, getConfigDir, isConfigured } from '../utils/config.js';
|
|
4
|
+
import { getDb } from '../db/client.js';
|
|
4
5
|
import { trackEvent } from '../utils/telemetry.js';
|
|
5
|
-
import { readJsonFileWithError, readFirebaseConfigFile, validateServiceAccountJson, validateWebConfig, extractServiceAccountConfig, looksLikeWebConfig, looksLikeServiceAccount, } from '../utils/firebase-json.js';
|
|
6
|
-
const DEFAULT_DASHBOARD_URL = 'https://code-insights.app';
|
|
7
6
|
/**
|
|
8
|
-
* Initialize Code Insights configuration
|
|
7
|
+
* Initialize Code Insights configuration.
|
|
8
|
+
* Sets up sync preferences and initializes the local SQLite database.
|
|
9
9
|
*/
|
|
10
|
-
export async function initCommand(
|
|
11
|
-
console.log(chalk.cyan('\n
|
|
12
|
-
// If --from-json or --web-config provided, auto-set firebase and proceed
|
|
13
|
-
if (options.fromJson || options.webConfig) {
|
|
14
|
-
return initFirebaseFlow(options, 'firebase');
|
|
15
|
-
}
|
|
10
|
+
export async function initCommand(_options = {}) {
|
|
11
|
+
console.log(chalk.cyan('\n Code Insights Setup\n'));
|
|
16
12
|
if (isConfigured()) {
|
|
17
13
|
const { overwrite } = await inquirer.prompt([
|
|
18
14
|
{
|
|
@@ -27,202 +23,29 @@ export async function initCommand(options) {
|
|
|
27
23
|
return;
|
|
28
24
|
}
|
|
29
25
|
}
|
|
30
|
-
//
|
|
31
|
-
const { dataSource } = await inquirer.prompt([
|
|
32
|
-
{
|
|
33
|
-
type: 'list',
|
|
34
|
-
name: 'dataSource',
|
|
35
|
-
message: 'How would you like to use Code Insights?',
|
|
36
|
-
choices: [
|
|
37
|
-
{
|
|
38
|
-
name: 'Local only (recommended) — stats from local session files, no cloud setup',
|
|
39
|
-
value: 'local',
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
name: 'Firebase — sync sessions to Firestore + web dashboard',
|
|
43
|
-
value: 'firebase',
|
|
44
|
-
},
|
|
45
|
-
],
|
|
46
|
-
default: 'local',
|
|
47
|
-
},
|
|
48
|
-
]);
|
|
49
|
-
if (dataSource === 'local') {
|
|
50
|
-
const config = {
|
|
51
|
-
sync: { claudeDir: '~/.claude/projects', excludeProjects: [] },
|
|
52
|
-
dataSource: 'local',
|
|
53
|
-
};
|
|
54
|
-
saveConfig(config);
|
|
55
|
-
console.log(chalk.green('\n✅ Configuration saved!'));
|
|
56
|
-
console.log(chalk.gray(`Config location: ${getConfigDir()}/config.json`));
|
|
57
|
-
console.log(chalk.cyan('\n🎉 Setup complete! Next steps:\n'));
|
|
58
|
-
console.log(chalk.white(' 1. View your stats:'));
|
|
59
|
-
console.log(chalk.gray(' code-insights stats\n'));
|
|
60
|
-
console.log(chalk.white(' 2. Check today\'s activity:'));
|
|
61
|
-
console.log(chalk.gray(' code-insights stats today\n'));
|
|
62
|
-
console.log(chalk.white(' 3. See cost breakdown:'));
|
|
63
|
-
console.log(chalk.gray(' code-insights stats cost\n'));
|
|
64
|
-
console.log(chalk.gray(' To switch to Firebase later: code-insights config set-source firebase\n'));
|
|
65
|
-
trackEvent('init', true);
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
// Firebase flow
|
|
69
|
-
return initFirebaseFlow(options, 'firebase');
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Firebase initialization flow — service account + web config
|
|
73
|
-
*/
|
|
74
|
-
async function initFirebaseFlow(options, dataSource) {
|
|
75
|
-
// --- Step 1: Service Account ---
|
|
76
|
-
let firebaseConfig;
|
|
77
|
-
if (options.fromJson) {
|
|
78
|
-
// Read from JSON file
|
|
79
|
-
const result = readJsonFileWithError(options.fromJson);
|
|
80
|
-
if (!result.success) {
|
|
81
|
-
console.log(chalk.red(`\n❌ ${result.message}`));
|
|
82
|
-
process.exit(1);
|
|
83
|
-
}
|
|
84
|
-
// Cross-type detection: did they pass a web config by mistake?
|
|
85
|
-
if (looksLikeWebConfig(result.data) && !looksLikeServiceAccount(result.data)) {
|
|
86
|
-
console.log(chalk.red('\n❌ This looks like a web config file, not a service account.'));
|
|
87
|
-
console.log(chalk.gray('Use --web-config for the web SDK config file.'));
|
|
88
|
-
console.log(chalk.gray('Use --from-json for the service account key (downloaded from Firebase).\n'));
|
|
89
|
-
process.exit(1);
|
|
90
|
-
}
|
|
91
|
-
if (!validateServiceAccountJson(result.data)) {
|
|
92
|
-
console.log(chalk.red('\n❌ Invalid service account JSON.'));
|
|
93
|
-
console.log(chalk.gray('Expected a file with: type, project_id, private_key, client_email'));
|
|
94
|
-
console.log(chalk.gray('Download it from: Firebase Console > Project Settings > Service Accounts\n'));
|
|
95
|
-
process.exit(1);
|
|
96
|
-
}
|
|
97
|
-
firebaseConfig = extractServiceAccountConfig(result.data);
|
|
98
|
-
console.log(chalk.green(`✓ Service account loaded from ${options.fromJson}`));
|
|
99
|
-
console.log(chalk.gray(` Project: ${firebaseConfig.projectId}`));
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
// Interactive prompts
|
|
103
|
-
console.log(chalk.bold('📋 Step 1: Service Account\n'));
|
|
104
|
-
console.log(chalk.gray('You\'ll need your Firebase service account key JSON file.'));
|
|
105
|
-
console.log(chalk.gray('Download from: Firebase Console > Project Settings > Service Accounts\n'));
|
|
106
|
-
console.log(chalk.gray(chalk.bold('Tip:') + ' Use --from-json <path> to skip these prompts:\n'));
|
|
107
|
-
console.log(chalk.gray(' code-insights init --from-json ~/Downloads/serviceAccountKey.json\n'));
|
|
108
|
-
const answers = await inquirer.prompt([
|
|
109
|
-
{
|
|
110
|
-
type: 'input',
|
|
111
|
-
name: 'projectId',
|
|
112
|
-
message: 'Firebase Project ID:',
|
|
113
|
-
validate: (input) => input.length > 0 || 'Project ID is required',
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
type: 'input',
|
|
117
|
-
name: 'clientEmail',
|
|
118
|
-
message: 'Service Account Email (client_email from JSON):',
|
|
119
|
-
validate: (input) => input.includes('@') || 'Please enter a valid service account email',
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
type: 'password',
|
|
123
|
-
name: 'privateKey',
|
|
124
|
-
message: 'Private Key (private_key from JSON, including BEGIN/END):',
|
|
125
|
-
validate: (input) => input.includes('PRIVATE KEY') || 'Please paste the complete private key',
|
|
126
|
-
},
|
|
127
|
-
]);
|
|
128
|
-
firebaseConfig = {
|
|
129
|
-
projectId: answers.projectId,
|
|
130
|
-
clientEmail: answers.clientEmail,
|
|
131
|
-
privateKey: answers.privateKey,
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
// --- Step 2: Web Config ---
|
|
135
|
-
let webConfig;
|
|
136
|
-
if (options.webConfig) {
|
|
137
|
-
// Read from file — supports both JSON and Firebase JS snippet format
|
|
138
|
-
const result = readFirebaseConfigFile(options.webConfig);
|
|
139
|
-
if (!result.success) {
|
|
140
|
-
console.log(chalk.red(`\n❌ ${result.message}`));
|
|
141
|
-
process.exit(1);
|
|
142
|
-
}
|
|
143
|
-
// Cross-type detection: did they pass a service account by mistake?
|
|
144
|
-
if (looksLikeServiceAccount(result.data) && !looksLikeWebConfig(result.data)) {
|
|
145
|
-
console.log(chalk.red('\n❌ This looks like a service account file, not a web config.'));
|
|
146
|
-
console.log(chalk.gray('Use --from-json for the service account key.'));
|
|
147
|
-
console.log(chalk.gray('Use --web-config for the web SDK config.\n'));
|
|
148
|
-
process.exit(1);
|
|
149
|
-
}
|
|
150
|
-
if (!validateWebConfig(result.data)) {
|
|
151
|
-
console.log(chalk.red('\n❌ Invalid web config.'));
|
|
152
|
-
console.log(chalk.gray('Expected: apiKey, authDomain, projectId, storageBucket, messagingSenderId, appId'));
|
|
153
|
-
console.log(chalk.gray('Get it from: Firebase Console > Project Settings > General > Your Apps'));
|
|
154
|
-
console.log(chalk.gray('You can paste the JavaScript snippet directly into a file — no need to convert to JSON.\n'));
|
|
155
|
-
process.exit(1);
|
|
156
|
-
}
|
|
157
|
-
webConfig = result.data;
|
|
158
|
-
console.log(chalk.green(`✓ Web config loaded from ${options.webConfig}`));
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
// Interactive prompts
|
|
162
|
-
console.log(chalk.bold('\n🌐 Step 2: Web Dashboard Config\n'));
|
|
163
|
-
console.log(chalk.gray('Get these from: Firebase Console > Project Settings > General > Your Apps\n'));
|
|
164
|
-
console.log(chalk.gray(chalk.bold('Tip:') + ' Save the config as a JSON file and use --web-config <path> to skip these prompts.\n'));
|
|
165
|
-
const answers = await inquirer.prompt([
|
|
166
|
-
{
|
|
167
|
-
type: 'input',
|
|
168
|
-
name: 'apiKey',
|
|
169
|
-
message: 'API Key (apiKey):',
|
|
170
|
-
validate: (input) => input.length > 0 || 'API Key is required',
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
type: 'input',
|
|
174
|
-
name: 'authDomain',
|
|
175
|
-
message: 'Auth Domain (authDomain):',
|
|
176
|
-
default: `${firebaseConfig.projectId}.firebaseapp.com`,
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
type: 'input',
|
|
180
|
-
name: 'storageBucket',
|
|
181
|
-
message: 'Storage Bucket (storageBucket):',
|
|
182
|
-
default: `${firebaseConfig.projectId}.appspot.com`,
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
type: 'input',
|
|
186
|
-
name: 'messagingSenderId',
|
|
187
|
-
message: 'Messaging Sender ID (messagingSenderId):',
|
|
188
|
-
validate: (input) => input.length > 0 || 'Messaging Sender ID is required',
|
|
189
|
-
},
|
|
190
|
-
{
|
|
191
|
-
type: 'input',
|
|
192
|
-
name: 'appId',
|
|
193
|
-
message: 'App ID (appId):',
|
|
194
|
-
validate: (input) => input.length > 0 || 'App ID is required',
|
|
195
|
-
},
|
|
196
|
-
]);
|
|
197
|
-
webConfig = {
|
|
198
|
-
apiKey: answers.apiKey,
|
|
199
|
-
authDomain: answers.authDomain,
|
|
200
|
-
projectId: firebaseConfig.projectId,
|
|
201
|
-
storageBucket: answers.storageBucket,
|
|
202
|
-
messagingSenderId: answers.messagingSenderId,
|
|
203
|
-
appId: answers.appId,
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
// --- Save config ---
|
|
26
|
+
// Save minimal config
|
|
207
27
|
const config = {
|
|
208
|
-
|
|
209
|
-
webConfig,
|
|
210
|
-
sync: {
|
|
211
|
-
claudeDir: '~/.claude/projects',
|
|
212
|
-
excludeProjects: [],
|
|
213
|
-
},
|
|
214
|
-
dataSource,
|
|
215
|
-
dashboardUrl: DEFAULT_DASHBOARD_URL,
|
|
28
|
+
sync: { claudeDir: '~/.claude/projects', excludeProjects: [] },
|
|
216
29
|
};
|
|
217
30
|
saveConfig(config);
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
31
|
+
// Initialize database (creates schema if first run)
|
|
32
|
+
try {
|
|
33
|
+
getDb();
|
|
34
|
+
console.log(chalk.green('\n Database initialized at ~/.code-insights/data.db'));
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
console.log(chalk.red(`\n Database initialization failed: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
console.log(chalk.green('\n Configuration saved!'));
|
|
41
|
+
console.log(chalk.gray(` Config location: ${getConfigDir()}/config.json`));
|
|
42
|
+
console.log(chalk.cyan('\n Setup complete! Next steps:\n'));
|
|
222
43
|
console.log(chalk.white(' 1. Sync your sessions:'));
|
|
223
44
|
console.log(chalk.gray(' code-insights sync\n'));
|
|
224
|
-
console.log(chalk.white(' 2.
|
|
225
|
-
console.log(chalk.gray(' code-insights
|
|
45
|
+
console.log(chalk.white(' 2. View your stats:'));
|
|
46
|
+
console.log(chalk.gray(' code-insights stats\n'));
|
|
47
|
+
console.log(chalk.white(' 3. Check today\'s activity:'));
|
|
48
|
+
console.log(chalk.gray(' code-insights stats today\n'));
|
|
226
49
|
trackEvent('init', true);
|
|
227
50
|
}
|
|
228
51
|
//# sourceMappingURL=init.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAOnD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,WAAwB,EAAE;IAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;IAErD,IAAI,YAAY,EAAE,EAAE,CAAC;QACnB,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;YAC1C;gBACE,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,0CAA0C;gBACnD,OAAO,EAAE,KAAK;aACf;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;IACH,CAAC;IAED,sBAAsB;IACtB,MAAM,MAAM,GAAwB;QAClC,IAAI,EAAE,EAAE,SAAS,EAAE,oBAAoB,EAAE,eAAe,EAAE,EAAE,EAAE;KAC/D,CAAC;IACF,UAAU,CAAC,MAAM,CAAC,CAAC;IAEnB,oDAAoD;IACpD,IAAI,CAAC;QACH,KAAK,EAAE,CAAC;QACR,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC,CAAC;IACnF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,uCAAuC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;QAC1H,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,sBAAsB,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC;IAE5E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC,CAAC;IAE5D,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC3B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install-hook.d.ts","sourceRoot":"","sources":["../../src/commands/install-hook.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"install-hook.d.ts","sourceRoot":"","sources":["../../src/commands/install-hook.ts"],"names":[],"mappings":"AA4BA;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAwDxD;AAED;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAqC1D"}
|
|
@@ -2,7 +2,6 @@ import * as fs from 'fs';
|
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import * as os from 'os';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
|
-
import { isConfigured, resolveDataSourcePreference } from '../utils/config.js';
|
|
6
5
|
import { trackEvent } from '../utils/telemetry.js';
|
|
7
6
|
const CLAUDE_SETTINGS_DIR = path.join(os.homedir(), '.claude');
|
|
8
7
|
const HOOKS_FILE = path.join(CLAUDE_SETTINGS_DIR, 'settings.json');
|
|
@@ -15,22 +14,6 @@ function getHookCommand(hook) {
|
|
|
15
14
|
*/
|
|
16
15
|
export async function installHookCommand() {
|
|
17
16
|
console.log(chalk.cyan('\n🔗 Install Code Insights Hook\n'));
|
|
18
|
-
// Check if configured
|
|
19
|
-
if (!isConfigured()) {
|
|
20
|
-
console.log(chalk.yellow('\n The auto-sync hook requires Firebase to be configured.\n'));
|
|
21
|
-
console.log(chalk.white(' To set up Firebase:'));
|
|
22
|
-
console.log(chalk.gray(' code-insights init\n'));
|
|
23
|
-
console.log(chalk.white(' For local-only analytics (no hook needed):'));
|
|
24
|
-
console.log(chalk.gray(' code-insights stats\n'));
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
const preference = resolveDataSourcePreference();
|
|
28
|
-
if (preference === 'local') {
|
|
29
|
-
console.log(chalk.yellow('\n ⚠ Data source is local. The auto-sync hook is only useful with Firebase.\n'));
|
|
30
|
-
console.log(chalk.gray(' Stats refresh automatically when you run `code-insights stats`.'));
|
|
31
|
-
console.log(chalk.gray(' To switch to Firebase: code-insights config set-source firebase\n'));
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
17
|
// Get CLI path
|
|
35
18
|
const cliPath = process.argv[1];
|
|
36
19
|
const syncCommand = `node ${cliPath} sync -q`;
|
|
@@ -67,12 +50,12 @@ export async function installHookCommand() {
|
|
|
67
50
|
// Write settings
|
|
68
51
|
fs.mkdirSync(CLAUDE_SETTINGS_DIR, { recursive: true });
|
|
69
52
|
fs.writeFileSync(HOOKS_FILE, JSON.stringify(settings, null, 2));
|
|
70
|
-
console.log(chalk.green('
|
|
53
|
+
console.log(chalk.green('Hook installed successfully!'));
|
|
71
54
|
console.log(chalk.gray(`\nConfiguration saved to: ${HOOKS_FILE}`));
|
|
72
55
|
console.log(chalk.cyan('\nHow it works:'));
|
|
73
|
-
console.log(chalk.white('
|
|
74
|
-
console.log(chalk.white('
|
|
75
|
-
console.log(chalk.white('
|
|
56
|
+
console.log(chalk.white(' When a Claude Code session ends, the hook runs automatically'));
|
|
57
|
+
console.log(chalk.white(' Sessions are synced to your local database (~/.code-insights/data.db)'));
|
|
58
|
+
console.log(chalk.white(' Run `code-insights stats` anytime to see your analytics'));
|
|
76
59
|
trackEvent('install-hook', true);
|
|
77
60
|
}
|
|
78
61
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install-hook.js","sourceRoot":"","sources":["../../src/commands/install-hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"install-hook.js","sourceRoot":"","sources":["../../src/commands/install-hook.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/open.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ interface OpenOptions {
|
|
|
2
2
|
project?: boolean;
|
|
3
3
|
}
|
|
4
4
|
/**
|
|
5
|
-
* Open the
|
|
5
|
+
* Open the local dashboard in the default browser.
|
|
6
|
+
* Note: requires `code-insights dashboard` server to be running (Phase 3).
|
|
6
7
|
*/
|
|
7
8
|
export declare function openCommand(options: OpenOptions): Promise<void>;
|
|
8
9
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../../src/commands/open.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../../src/commands/open.ts"],"names":[],"mappings":"AAUA,UAAU,WAAW;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BrE"}
|
package/dist/commands/open.js
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
import { execFile } from 'child_process';
|
|
2
1
|
import path from 'path';
|
|
3
2
|
import chalk from 'chalk';
|
|
4
3
|
import { loadConfig } from '../utils/config.js';
|
|
5
4
|
import { trackEvent } from '../utils/telemetry.js';
|
|
6
|
-
|
|
5
|
+
import { openUrl } from '../utils/browser.js';
|
|
6
|
+
// Phase 3: local Hono server will listen on this port.
|
|
7
|
+
// `code-insights dashboard` command will start the server first.
|
|
8
|
+
const DEFAULT_DASHBOARD_PORT = 7890;
|
|
7
9
|
/**
|
|
8
|
-
* Open the
|
|
10
|
+
* Open the local dashboard in the default browser.
|
|
11
|
+
* Note: requires `code-insights dashboard` server to be running (Phase 3).
|
|
9
12
|
*/
|
|
10
13
|
export async function openCommand(options) {
|
|
11
14
|
const config = loadConfig();
|
|
12
|
-
const
|
|
15
|
+
const port = config?.dashboard?.port ?? DEFAULT_DASHBOARD_PORT;
|
|
16
|
+
const baseUrl = `http://localhost:${port}`;
|
|
13
17
|
let url = baseUrl;
|
|
14
18
|
// If --project flag, try to detect current project name from cwd
|
|
15
19
|
if (options.project) {
|
|
@@ -19,8 +23,9 @@ export async function openCommand(options) {
|
|
|
19
23
|
}
|
|
20
24
|
}
|
|
21
25
|
console.log(chalk.cyan(`\n Opening ${url}\n`));
|
|
26
|
+
console.log(chalk.gray(' (Run `code-insights dashboard` to start the local server if needed)\n'));
|
|
22
27
|
try {
|
|
23
|
-
|
|
28
|
+
openUrl(url);
|
|
24
29
|
trackEvent('open', true);
|
|
25
30
|
}
|
|
26
31
|
catch {
|
|
@@ -29,22 +34,6 @@ export async function openCommand(options) {
|
|
|
29
34
|
trackEvent('open', false);
|
|
30
35
|
}
|
|
31
36
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Open a URL in the default browser using platform-specific commands.
|
|
34
|
-
* Uses execFile (not exec) to prevent shell injection.
|
|
35
|
-
*/
|
|
36
|
-
function openInBrowser(url) {
|
|
37
|
-
const platform = process.platform;
|
|
38
|
-
if (platform === 'darwin') {
|
|
39
|
-
execFile('open', [url]);
|
|
40
|
-
}
|
|
41
|
-
else if (platform === 'win32') {
|
|
42
|
-
execFile('cmd', ['/c', 'start', '', url]);
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
execFile('xdg-open', [url]);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
37
|
/**
|
|
49
38
|
* Get the current directory name as a project name guess.
|
|
50
39
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"open.js","sourceRoot":"","sources":["../../src/commands/open.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"open.js","sourceRoot":"","sources":["../../src/commands/open.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C,uDAAuD;AACvD,iEAAiE;AACjE,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAMpC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAoB;IACpD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,MAAM,EAAE,SAAS,EAAE,IAAI,IAAI,sBAAsB,CAAC;IAC/D,MAAM,OAAO,GAAG,oBAAoB,IAAI,EAAE,CAAC;IAE3C,IAAI,GAAG,GAAG,OAAO,CAAC;IAElB,iEAAiE;IACjE,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,WAAW,GAAG,qBAAqB,EAAE,CAAC;QAC5C,IAAI,WAAW,EAAE,CAAC;YAChB,GAAG,GAAG,GAAG,OAAO,qBAAqB,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAC;QACzE,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,yEAAyE,CAAC,CAAC,CAAC;IAEnG,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,CAAC;QACb,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC,CAAC;QACrE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QACpE,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,qBAAqB;IAC5B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reset.d.ts","sourceRoot":"","sources":["../../src/commands/reset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"reset.d.ts","sourceRoot":"","sources":["../../src/commands/reset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,eAAO,MAAM,YAAY,SAyErB,CAAC"}
|
package/dist/commands/reset.js
CHANGED
|
@@ -1,28 +1,17 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import ora from 'ora';
|
|
4
|
-
import admin from 'firebase-admin';
|
|
5
4
|
import { existsSync, unlinkSync } from 'fs';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { loadConfig, resolveDataSourcePreference } from '../utils/config.js';
|
|
5
|
+
import { getDb, getDbPath } from '../db/client.js';
|
|
6
|
+
import { getSyncStatePath } from '../utils/config.js';
|
|
9
7
|
import { trackEvent } from '../utils/telemetry.js';
|
|
10
|
-
const SYNC_STATE_FILE = join(homedir(), '.code-insights', 'sync-state.json');
|
|
11
8
|
export const resetCommand = new Command('reset')
|
|
12
|
-
.description('Delete all data from
|
|
9
|
+
.description('Delete all synced data from the local SQLite database and reset sync state')
|
|
13
10
|
.option('--confirm', 'Skip confirmation prompt')
|
|
14
11
|
.action(async (options) => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
console.log(chalk.yellow('\n ⚠ Data source is local. Nothing to reset in Firestore.\n'));
|
|
18
|
-
console.log(chalk.gray(' To clear the local stats cache:'));
|
|
19
|
-
console.log(chalk.gray(' rm ~/.code-insights/stats-cache.json\n'));
|
|
20
|
-
process.exit(0);
|
|
21
|
-
}
|
|
22
|
-
console.log(chalk.red.bold('\n⚠️ WARNING: This will permanently delete ALL data from your Firestore database!'));
|
|
23
|
-
console.log(chalk.yellow('Collections to be deleted: projects, sessions, insights, messages\n'));
|
|
12
|
+
console.log(chalk.red.bold('\n WARNING: This will permanently delete ALL synced data from your local database!'));
|
|
13
|
+
console.log(chalk.yellow(' Tables to be cleared: projects, sessions, messages, insights, usage_stats\n'));
|
|
24
14
|
if (!options.confirm) {
|
|
25
|
-
// Simple confirmation using stdin
|
|
26
15
|
const readline = await import('readline');
|
|
27
16
|
const rl = readline.createInterface({
|
|
28
17
|
input: process.stdin,
|
|
@@ -37,44 +26,36 @@ export const resetCommand = new Command('reset')
|
|
|
37
26
|
process.exit(0);
|
|
38
27
|
}
|
|
39
28
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
projectId: config.firebase.projectId,
|
|
55
|
-
clientEmail: config.firebase.clientEmail,
|
|
56
|
-
privateKey: config.firebase.privateKey.replace(/\\n/g, '\n'),
|
|
57
|
-
}),
|
|
29
|
+
console.log('');
|
|
30
|
+
// Delete SQLite data — all 5 DELETEs wrapped in a single transaction.
|
|
31
|
+
// If any DELETE fails, the transaction rolls back atomically and we do NOT
|
|
32
|
+
// proceed to delete the sync state file (which would leave them out of sync).
|
|
33
|
+
const dbSpinner = ora('Clearing database...').start();
|
|
34
|
+
try {
|
|
35
|
+
const db = getDb();
|
|
36
|
+
const clearAll = db.transaction(() => {
|
|
37
|
+
// Delete in dependency order (FK constraints)
|
|
38
|
+
db.prepare('DELETE FROM insights').run();
|
|
39
|
+
db.prepare('DELETE FROM messages').run();
|
|
40
|
+
db.prepare('DELETE FROM sessions').run();
|
|
41
|
+
db.prepare('DELETE FROM projects').run();
|
|
42
|
+
db.prepare('DELETE FROM usage_stats').run();
|
|
58
43
|
});
|
|
44
|
+
clearAll();
|
|
45
|
+
dbSpinner.succeed(`Database cleared (${getDbPath()})`);
|
|
59
46
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
const deleted = await deleteCollection(db, collectionName);
|
|
67
|
-
spinner.succeed(`Deleted ${deleted} documents from ${collectionName}`);
|
|
68
|
-
}
|
|
69
|
-
catch (error) {
|
|
70
|
-
spinner.fail(`Failed to delete ${collectionName}: ${error}`);
|
|
71
|
-
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
dbSpinner.fail(`Failed to clear database: ${error instanceof Error ? error.message : error}`);
|
|
49
|
+
console.error(chalk.red('\nAborted. Sync state was NOT deleted to avoid inconsistency.'));
|
|
50
|
+
console.error(chalk.dim('Run `code-insights doctor` if the problem persists.'));
|
|
51
|
+
process.exit(1);
|
|
72
52
|
}
|
|
73
|
-
// Delete local sync state
|
|
53
|
+
// Delete local sync state — only reached if DB clear succeeded
|
|
54
|
+
const syncStatePath = getSyncStatePath();
|
|
74
55
|
const syncSpinner = ora('Removing local sync state...').start();
|
|
75
56
|
try {
|
|
76
|
-
if (existsSync(
|
|
77
|
-
unlinkSync(
|
|
57
|
+
if (existsSync(syncStatePath)) {
|
|
58
|
+
unlinkSync(syncStatePath);
|
|
78
59
|
syncSpinner.succeed('Removed local sync state');
|
|
79
60
|
}
|
|
80
61
|
else {
|
|
@@ -84,26 +65,14 @@ export const resetCommand = new Command('reset')
|
|
|
84
65
|
catch (error) {
|
|
85
66
|
syncSpinner.fail(`Failed to remove sync state: ${error}`);
|
|
86
67
|
}
|
|
87
|
-
|
|
88
|
-
|
|
68
|
+
// Collect stats for telemetry before resetting
|
|
69
|
+
try {
|
|
70
|
+
trackEvent('reset', true);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// non-fatal
|
|
74
|
+
}
|
|
75
|
+
console.log(chalk.green('\n Reset complete. Run `code-insights sync` to re-sync all sessions.\n'));
|
|
89
76
|
process.exit(0);
|
|
90
77
|
});
|
|
91
|
-
async function deleteCollection(db, collectionName) {
|
|
92
|
-
const collectionRef = db.collection(collectionName);
|
|
93
|
-
const batchSize = 500;
|
|
94
|
-
let totalDeleted = 0;
|
|
95
|
-
while (true) {
|
|
96
|
-
const snapshot = await collectionRef.limit(batchSize).get();
|
|
97
|
-
if (snapshot.empty) {
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
const batch = db.batch();
|
|
101
|
-
snapshot.docs.forEach((doc) => {
|
|
102
|
-
batch.delete(doc.ref);
|
|
103
|
-
});
|
|
104
|
-
await batch.commit();
|
|
105
|
-
totalDeleted += snapshot.size;
|
|
106
|
-
}
|
|
107
|
-
return totalDeleted;
|
|
108
|
-
}
|
|
109
78
|
//# sourceMappingURL=reset.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reset.js","sourceRoot":"","sources":["../../src/commands/reset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,
|
|
1
|
+
{"version":3,"file":"reset.js","sourceRoot":"","sources":["../../src/commands/reset.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../../../src/commands/stats/actions/error-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../../../src/commands/stats/actions/error-handler.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,CAqBpD"}
|