1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'fs' ;
4
+ import path from 'path' ;
5
+ import { fileURLToPath } from 'url' ;
6
+
7
+ const __filename = fileURLToPath ( import . meta. url ) ;
8
+ const __dirname = path . dirname ( __filename ) ;
9
+
10
+ /**
11
+ * Checks version consistency across all package.json files in the monorepo
12
+ * Exits with code 1 if versions are inconsistent
13
+ * Usage: node scripts/check-version-consistency.js
14
+ */
15
+
16
+ console . log ( '🔍 Checking version consistency across packages...\n' ) ;
17
+
18
+ // List of package.json files to check
19
+ const packagePaths = [
20
+ 'package.json' ,
21
+ 'client/package.json' ,
22
+ 'server/package.json' ,
23
+ 'cli/package.json'
24
+ ] ;
25
+
26
+ const versions = new Map ( ) ;
27
+ const errors = [ ] ;
28
+
29
+ // Read version from each package.json
30
+ packagePaths . forEach ( packagePath => {
31
+ const fullPath = path . join ( __dirname , '..' , packagePath ) ;
32
+
33
+ if ( ! fs . existsSync ( fullPath ) ) {
34
+ console . warn ( `⚠️ Skipping ${ packagePath } - file not found` ) ;
35
+ return ;
36
+ }
37
+
38
+ try {
39
+ const packageJson = JSON . parse ( fs . readFileSync ( fullPath , 'utf8' ) ) ;
40
+ const version = packageJson . version ;
41
+ const packageName = packageJson . name || packagePath ;
42
+
43
+ versions . set ( packagePath , {
44
+ name : packageName ,
45
+ version : version ,
46
+ dependencies : packageJson . dependencies || { }
47
+ } ) ;
48
+
49
+ console . log ( `📦 ${ packagePath } :` ) ;
50
+ console . log ( ` Name: ${ packageName } ` ) ;
51
+ console . log ( ` Version: ${ version } ` ) ;
52
+ } catch ( error ) {
53
+ errors . push ( `Failed to read ${ packagePath } : ${ error . message } ` ) ;
54
+ }
55
+ } ) ;
56
+
57
+ if ( errors . length > 0 ) {
58
+ console . error ( '\n❌ Errors occurred while reading package files:' ) ;
59
+ errors . forEach ( error => console . error ( ` - ${ error } ` ) ) ;
60
+ process . exit ( 1 ) ;
61
+ }
62
+
63
+ // Check if all versions match
64
+ const allVersions = Array . from ( versions . values ( ) ) . map ( v => v . version ) ;
65
+ const uniqueVersions = [ ...new Set ( allVersions ) ] ;
66
+
67
+ console . log ( '\n📊 Version Summary:' ) ;
68
+ console . log ( ` Total packages: ${ versions . size } ` ) ;
69
+ console . log ( ` Unique versions: ${ uniqueVersions . length } ` ) ;
70
+
71
+ if ( uniqueVersions . length > 1 ) {
72
+ console . error ( '\n❌ Version mismatch detected!' ) ;
73
+ console . error ( ' Found versions: ' + uniqueVersions . join ( ', ' ) ) ;
74
+
75
+ console . error ( '\n Package versions:' ) ;
76
+ versions . forEach ( ( info , path ) => {
77
+ console . error ( ` - ${ path } : ${ info . version } ` ) ;
78
+ } ) ;
79
+ } else {
80
+ console . log ( ` ✅ All packages are at version: ${ uniqueVersions [ 0 ] } ` ) ;
81
+ }
82
+
83
+ // Check workspace dependencies in root package.json
84
+ const rootPackage = versions . get ( 'package.json' ) ;
85
+ if ( rootPackage ) {
86
+ console . log ( '\n🔗 Checking workspace dependencies...' ) ;
87
+ const expectedVersion = rootPackage . version ;
88
+ let dependencyErrors = false ;
89
+
90
+ Object . entries ( rootPackage . dependencies ) . forEach ( ( [ dep , version ] ) => {
91
+ if ( dep . startsWith ( '@modelcontextprotocol/inspector-' ) ) {
92
+ const expectedDepVersion = `^${ expectedVersion } ` ;
93
+ if ( version !== expectedDepVersion ) {
94
+ console . error ( ` ❌ ${ dep } : ${ version } (expected ${ expectedDepVersion } )` ) ;
95
+ dependencyErrors = true ;
96
+ } else {
97
+ console . log ( ` ✅ ${ dep } : ${ version } ` ) ;
98
+ }
99
+ }
100
+ } ) ;
101
+
102
+ if ( dependencyErrors ) {
103
+ errors . push ( 'Workspace dependency versions do not match package versions' ) ;
104
+ }
105
+ }
106
+
107
+ // Check if package-lock.json is up to date
108
+ console . log ( '\n🔒 Checking package-lock.json...' ) ;
109
+ const lockPath = path . join ( __dirname , '..' , 'package-lock.json' ) ;
110
+ let lockFileError = false ;
111
+
112
+ if ( ! fs . existsSync ( lockPath ) ) {
113
+ console . error ( ' ❌ package-lock.json not found' ) ;
114
+ lockFileError = true ;
115
+ } else {
116
+ try {
117
+ const lockFile = JSON . parse ( fs . readFileSync ( lockPath , 'utf8' ) ) ;
118
+ const lockVersion = lockFile . version ;
119
+ const expectedVersion = rootPackage ?. version || uniqueVersions [ 0 ] ;
120
+
121
+ if ( lockVersion !== expectedVersion ) {
122
+ console . error ( ` ❌ package-lock.json version (${ lockVersion } ) does not match package.json version (${ expectedVersion } )` ) ;
123
+ lockFileError = true ;
124
+ } else {
125
+ console . log ( ` ✅ package-lock.json version matches: ${ lockVersion } ` ) ;
126
+ }
127
+
128
+ // Check workspace package versions in lock file
129
+ if ( lockFile . packages ) {
130
+ const workspacePackages = [
131
+ { path : 'client' , name : '@modelcontextprotocol/inspector-client' } ,
132
+ { path : 'server' , name : '@modelcontextprotocol/inspector-server' } ,
133
+ { path : 'cli' , name : '@modelcontextprotocol/inspector-cli' }
134
+ ] ;
135
+
136
+ workspacePackages . forEach ( ( { path, name } ) => {
137
+ const lockPkgPath = lockFile . packages [ path ] ;
138
+ if ( lockPkgPath && lockPkgPath . version !== expectedVersion ) {
139
+ console . error ( ` ❌ ${ name } in lock file: ${ lockPkgPath . version } (expected ${ expectedVersion } )` ) ;
140
+ lockFileError = true ;
141
+ }
142
+ } ) ;
143
+ }
144
+ } catch ( error ) {
145
+ console . error ( ` ❌ Failed to parse package-lock.json: ${ error . message } ` ) ;
146
+ lockFileError = true ;
147
+ }
148
+ }
149
+
150
+ // Final result
151
+ console . log ( '\n🎯 Result:' ) ;
152
+ if ( uniqueVersions . length === 1 && errors . length === 0 && ! lockFileError ) {
153
+ console . log ( ' ✅ Version consistency check passed!' ) ;
154
+ process . exit ( 0 ) ;
155
+ } else {
156
+ console . error ( ' ❌ Version consistency check failed!' ) ;
157
+ if ( uniqueVersions . length > 1 ) {
158
+ console . error ( ' - Package versions are not consistent' ) ;
159
+ }
160
+ if ( errors . length > 0 ) {
161
+ console . error ( ' - ' + errors . join ( '\n - ' ) ) ;
162
+ }
163
+ if ( lockFileError ) {
164
+ console . error ( ' - package-lock.json is out of sync' ) ;
165
+ }
166
+ console . error ( '\n💡 Run "npm run update-version <new-version>" to fix version inconsistencies' ) ;
167
+ console . error ( ' or run "npm install" to update package-lock.json' ) ;
168
+ process . exit ( 1 ) ;
169
+ }
0 commit comments