maven-indexer-mcp 1.0.7 → 1.0.8

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/build/db/index.js CHANGED
@@ -1,13 +1,26 @@
1
1
  import Database from 'better-sqlite3';
2
2
  import path from 'path';
3
+ import os from 'os';
4
+ import fs from 'fs';
3
5
  export class DB {
4
6
  static instance;
5
7
  db;
6
8
  constructor() {
7
9
  // Check environment variable for DB path (useful for testing)
8
- const dbName = process.env.DB_FILE || 'maven-index.sqlite';
9
- const dbPath = path.join(process.cwd(), dbName);
10
- this.db = new Database(dbPath);
10
+ if (process.env.DB_FILE) {
11
+ this.db = new Database(process.env.DB_FILE);
12
+ }
13
+ else {
14
+ // Use home directory for the database file
15
+ const homeDir = os.homedir();
16
+ const configDir = path.join(homeDir, '.maven-indexer-mcp');
17
+ // Ensure the directory exists
18
+ if (!fs.existsSync(configDir)) {
19
+ fs.mkdirSync(configDir, { recursive: true });
20
+ }
21
+ const dbPath = path.join(configDir, 'maven-index.sqlite');
22
+ this.db = new Database(dbPath);
23
+ }
11
24
  this.initSchema();
12
25
  }
13
26
  static getInstance() {
package/build/indexer.js CHANGED
@@ -15,6 +15,7 @@ export class Indexer {
15
15
  isIndexing = false;
16
16
  watcher = null;
17
17
  debounceTimer = null;
18
+ pollingTimer = null;
18
19
  constructor() {
19
20
  }
20
21
  static getInstance() {
@@ -24,55 +25,95 @@ export class Indexer {
24
25
  return Indexer.instance;
25
26
  }
26
27
  /**
27
- * Starts watching the local repository for changes.
28
- * Debounces changes to trigger re-indexing.
28
+ * Starts watching the local repository for changes - ULTRA SIMPLE VERSION
29
+ * Just watch the root directories without recursion
29
30
  */
30
31
  async startWatch() {
31
32
  const config = await Config.getInstance();
32
- const pathsToWatch = [];
33
+ const watchPaths = [];
34
+ // Simple: Just add the main repository paths
33
35
  if (config.localRepository && fsSync.existsSync(config.localRepository)) {
34
- pathsToWatch.push(config.localRepository);
36
+ watchPaths.push(config.localRepository);
35
37
  }
36
38
  if (config.gradleRepository && fsSync.existsSync(config.gradleRepository)) {
37
- pathsToWatch.push(config.gradleRepository);
39
+ watchPaths.push(config.gradleRepository);
38
40
  }
39
- if (pathsToWatch.length === 0) {
41
+ if (watchPaths.length === 0) {
40
42
  console.error("No repository paths found, skipping watch mode.");
41
43
  return;
42
44
  }
43
- if (this.watcher) {
45
+ if (this.watcher || this.pollingTimer) {
44
46
  return;
45
47
  }
46
- console.error(`Starting file watcher on ${pathsToWatch.join(', ')}...`);
47
- this.watcher = chokidar.watch(pathsToWatch, {
48
- ignored: (p) => {
49
- // Don't ignore the root paths themselves
50
- if (pathsToWatch.includes(p))
51
- return false;
52
- // Ignore dotfiles/dotdirs
53
- return path.basename(p).startsWith('.');
54
- },
55
- persistent: true,
56
- ignoreInitial: true,
57
- depth: 10 // Limit depth to avoid too much overhead? Standard maven repo depth is around 3-5
58
- });
59
- const onChange = () => {
60
- if (this.debounceTimer)
61
- clearTimeout(this.debounceTimer);
62
- this.debounceTimer = setTimeout(() => {
63
- console.error("Repository change detected. Triggering re-index...");
64
- this.index().catch(console.error);
65
- }, 5000); // Debounce for 5 seconds
66
- };
67
- this.watcher
68
- .on('add', (path) => {
69
- if (path.endsWith('.jar') || path.endsWith('.pom'))
70
- onChange();
71
- })
72
- .on('unlink', (path) => {
73
- if (path.endsWith('.jar') || path.endsWith('.pom'))
74
- onChange();
75
- });
48
+ console.error(`🔍 Starting ultra-simple file watcher on: ${watchPaths.join(', ')}`);
49
+ try {
50
+ // ULTRA SIMPLE: Watch only root directories, no recursion
51
+ this.watcher = chokidar.watch(watchPaths, {
52
+ // Watch only the root directory itself, not subdirectories
53
+ depth: 0,
54
+ // Don't trigger for files that already exist
55
+ ignoreInitial: true,
56
+ // Wait for files to finish writing before triggering
57
+ awaitWriteFinish: {
58
+ stabilityThreshold: 2000,
59
+ pollInterval: 100
60
+ },
61
+ // Don't crash on permission errors
62
+ ignorePermissionErrors: true
63
+ });
64
+ // SIMPLE: Watch for any changes in the root directories
65
+ // This will catch when new directories are created (which means new artifacts)
66
+ this.watcher
67
+ .on('addDir', (dirPath) => {
68
+ console.error(`� New directory detected: ${path.basename(dirPath)}`);
69
+ this.triggerReindex();
70
+ })
71
+ .on('unlinkDir', (dirPath) => {
72
+ console.error(`🗑️ Directory removed: ${path.basename(dirPath)}`);
73
+ this.triggerReindex();
74
+ })
75
+ .on('error', (error) => {
76
+ const errorMessage = error instanceof Error ? error.message : String(error);
77
+ console.error(`❌ Watcher error: ${errorMessage}`);
78
+ this.fallbackToPolling();
79
+ });
80
+ console.error('✅ Ultra-simple file watcher started successfully');
81
+ }
82
+ catch (error) {
83
+ const errorMessage = error instanceof Error ? error.message : String(error);
84
+ console.error(`❌ Failed to start watcher: ${errorMessage}`);
85
+ this.fallbackToPolling();
86
+ }
87
+ }
88
+ /**
89
+ * Falls back to polling mode if watcher fails.
90
+ * Polls the repository every 1 min
91
+ */
92
+ fallbackToPolling() {
93
+ if (this.pollingTimer) {
94
+ return;
95
+ }
96
+ console.error('⚠️ Falling back to polling mode (every 10s)...');
97
+ if (this.watcher) {
98
+ this.watcher.close().catch(err => console.error(`Error closing watcher: ${err}`));
99
+ this.watcher = null;
100
+ }
101
+ this.pollingTimer = setInterval(() => {
102
+ this.index().catch(console.error);
103
+ }, 60000);
104
+ }
105
+ /**
106
+ * Trigger reindexing with debouncing (wait a bit for multiple changes)
107
+ */
108
+ triggerReindex() {
109
+ if (this.debounceTimer) {
110
+ clearTimeout(this.debounceTimer);
111
+ }
112
+ // Wait 3 seconds after the last change before reindexing
113
+ this.debounceTimer = setTimeout(() => {
114
+ console.error('🔄 Changes detected - triggering reindex...');
115
+ this.index().catch(console.error);
116
+ }, 3000);
76
117
  }
77
118
  /**
78
119
  * Forces a full re-index of the repository.
@@ -0,0 +1,121 @@
1
+ /**
2
+ * SIMPLIFIED FILE WATCHER for Maven Indexer
3
+ *
4
+ * This is a cleaned-up version that's easier to understand.
5
+ * It watches for new JAR and POM files in your Maven/Gradle repositories.
6
+ */
7
+ import fs from 'fs';
8
+ import path from 'path';
9
+ export class SimpleWatcher {
10
+ watcher = null;
11
+ onChangeCallback;
12
+ constructor(onChangeCallback) {
13
+ this.onChangeCallback = onChangeCallback;
14
+ }
15
+ /**
16
+ * Start watching - SIMPLE VERSION
17
+ * Just watch the main folders and filter for JAR/POM files
18
+ */
19
+ async startWatching(mavenRepoPath, gradleRepoPath) {
20
+ if (this.watcher) {
21
+ console.log('Watcher already running');
22
+ return;
23
+ }
24
+ const watchPaths = [];
25
+ // Add Maven repo if it exists
26
+ if (mavenRepoPath && fs.existsSync(mavenRepoPath)) {
27
+ watchPaths.push(mavenRepoPath);
28
+ }
29
+ // Add Gradle repo if it exists
30
+ if (gradleRepoPath && fs.existsSync(gradleRepoPath)) {
31
+ watchPaths.push(gradleRepoPath);
32
+ }
33
+ if (watchPaths.length === 0) {
34
+ console.log('No repository paths to watch');
35
+ return;
36
+ }
37
+ console.log(`🔍 Watching for new JAR/POM files in: ${watchPaths.join(', ')}`);
38
+ // SIMPLE: Use chokidar with basic ignore patterns
39
+ const chokidar = await import('chokidar');
40
+ this.watcher = chokidar.watch(watchPaths, {
41
+ // Ignore common junk files (simple patterns)
42
+ ignored: [
43
+ '**/.*', // Hidden files
44
+ '**/*.tmp', // Temp files
45
+ '**/*.sha1', // Checksum files
46
+ '**/*.sha256', // Checksum files
47
+ '**/*.md5', // Checksum files
48
+ ],
49
+ // Don't watch too deep (Maven repos are usually 3-4 levels)
50
+ depth: 6,
51
+ // Don't trigger for files that already exist
52
+ ignoreInitial: true,
53
+ // Wait for files to finish writing before triggering
54
+ awaitWriteFinish: {
55
+ stabilityThreshold: 2000, // Wait 2 seconds after file stops changing
56
+ pollInterval: 100
57
+ }
58
+ });
59
+ // SIMPLE: Just watch for new files being added
60
+ this.watcher
61
+ .on('add', (filePath) => {
62
+ // Only care about JAR and POM files
63
+ if (filePath.endsWith('.jar') || filePath.endsWith('.pom')) {
64
+ console.log(`📦 New file detected: ${path.basename(filePath)}`);
65
+ this.triggerReindex();
66
+ }
67
+ })
68
+ .on('unlink', (filePath) => {
69
+ // Also watch for files being deleted
70
+ if (filePath.endsWith('.jar') || filePath.endsWith('.pom')) {
71
+ console.log(`🗑️ File removed: ${path.basename(filePath)}`);
72
+ this.triggerReindex();
73
+ }
74
+ })
75
+ .on('error', (error) => {
76
+ console.log(`❌ Watcher error: ${error.message}`);
77
+ });
78
+ console.log('✅ File watcher started successfully');
79
+ }
80
+ /**
81
+ * Stop watching
82
+ */
83
+ stopWatching() {
84
+ if (this.watcher) {
85
+ this.watcher.close();
86
+ this.watcher = null;
87
+ console.log('🛑 File watcher stopped');
88
+ }
89
+ }
90
+ /**
91
+ * Trigger reindexing with debouncing (wait a bit for multiple changes)
92
+ */
93
+ debounceTimer = null;
94
+ triggerReindex() {
95
+ // Clear any existing timer
96
+ if (this.debounceTimer) {
97
+ clearTimeout(this.debounceTimer);
98
+ }
99
+ // Wait 3 seconds after the last change before reindexing
100
+ this.debounceTimer = setTimeout(() => {
101
+ console.log('🔄 Changes detected - triggering reindex...');
102
+ this.onChangeCallback();
103
+ }, 3000);
104
+ }
105
+ }
106
+ /**
107
+ * USAGE EXAMPLE:
108
+ *
109
+ * const watcher = new SimpleWatcher(() => {
110
+ * console.log('Time to reindex the repository!');
111
+ * // Put your reindexing code here
112
+ * });
113
+ *
114
+ * await watcher.startWatching(
115
+ * '/Users/tangcent/.m2/repository',
116
+ * '/Users/tangcent/.gradle/caches/modules-2/files-2.1'
117
+ * );
118
+ *
119
+ * // Later... when you want to stop
120
+ * watcher.stopWatching();
121
+ **/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maven-indexer-mcp",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "MCP server for indexing local Maven repository",
5
5
  "main": "build/index.js",
6
6
  "type": "module",