99
1010namespace DevProxy . Abstractions . Utils ;
1111
12- public static class MSGraphDbUtils
12+ public sealed class MSGraphDbUtils ( HttpClient httpClient , ILogger < MSGraphDbUtils > logger ) : IDisposable
1313{
14- private static readonly Dictionary < string , OpenApiDocument > _openApiDocuments = [ ] ;
1514 private static readonly string [ ] graphVersions = [ "v1.0" , "beta" ] ;
16-
17- private static SqliteConnection ? _msGraphDbConnection ;
15+ private readonly Dictionary < string , OpenApiDocument > _openApiDocuments = [ ] ;
16+ private readonly HttpClient _httpClient = httpClient ;
17+ private readonly ILogger < MSGraphDbUtils > _logger = logger ;
18+ private SqliteConnection ? _msGraphDbConnection ;
1819
1920 // v1 refers to v1 of the db schema, not the graph version
2021 public static string MSGraphDbFilePath => Path . Combine ( ProxyUtils . AppFolder ! , "msgraph-openapi-v1.db" ) ;
2122
22- public static SqliteConnection MSGraphDbConnection
23+ public SqliteConnection MSGraphDbConnection
2324 {
2425 get
2526 {
@@ -33,12 +34,12 @@ public static SqliteConnection MSGraphDbConnection
3334 }
3435 }
3536
36- public static async Task < int > GenerateMSGraphDbAsync ( ILogger logger , bool skipIfUpdatedToday , CancellationToken cancellationToken )
37+ public async Task < int > GenerateMSGraphDbAsync ( bool skipIfUpdatedToday , CancellationToken cancellationToken )
3738 {
3839 var appFolder = ProxyUtils . AppFolder ;
3940 if ( string . IsNullOrEmpty ( appFolder ) )
4041 {
41- logger . LogError ( "App folder {AppFolder} not found" , appFolder ) ;
42+ _logger . LogError ( "App folder {AppFolder} not found" , appFolder ) ;
4243 return 1 ;
4344 }
4445
@@ -48,61 +49,64 @@ public static async Task<int> GenerateMSGraphDbAsync(ILogger logger, bool skipIf
4849 var modifiedToday = dbFileInfo . Exists && dbFileInfo . LastWriteTime . Date == DateTime . Now . Date ;
4950 if ( modifiedToday && skipIfUpdatedToday )
5051 {
51- logger . LogInformation ( "Microsoft Graph database already updated today" ) ;
52+ _logger . LogInformation ( "Microsoft Graph database already updated today" ) ;
5253 return 1 ;
5354 }
5455
55- await UpdateOpenAPIGraphFilesIfNecessaryAsync ( appFolder , logger , cancellationToken ) ;
56- await LoadOpenAPIFilesAsync ( appFolder , logger , cancellationToken ) ;
56+ await UpdateOpenAPIGraphFilesIfNecessaryAsync ( appFolder , cancellationToken ) ;
57+ await LoadOpenAPIFilesAsync ( appFolder , cancellationToken ) ;
5758 if ( _openApiDocuments . Count < 1 )
5859 {
59- logger . LogDebug ( "No OpenAPI files found or couldn't load them" ) ;
60+ _logger . LogDebug ( "No OpenAPI files found or couldn't load them" ) ;
6061 return 1 ;
6162 }
6263
63- var dbConnection = MSGraphDbConnection ;
64- await CreateDbAsync ( dbConnection , logger , cancellationToken ) ;
65- await FillDataAsync ( dbConnection , logger , cancellationToken ) ;
64+ await CreateDbAsync ( cancellationToken ) ;
65+ await FillDataAsync ( cancellationToken ) ;
6666
67- logger . LogInformation ( "Microsoft Graph database successfully updated" ) ;
67+ _logger . LogInformation ( "Microsoft Graph database successfully updated" ) ;
6868
6969 return 0 ;
7070 }
7171 catch ( Exception ex )
7272 {
73- logger . LogError ( ex , "Error generating Microsoft Graph database" ) ;
73+ _logger . LogError ( ex , "Error generating Microsoft Graph database" ) ;
7474 return 1 ;
7575 }
7676
7777 }
7878
7979 private static string GetGraphOpenApiYamlFileName ( string version ) => $ "graph-{ version . Replace ( "." , "_" , StringComparison . OrdinalIgnoreCase ) } -openapi.yaml";
8080
81- private static async Task CreateDbAsync ( SqliteConnection dbConnection , ILogger logger , CancellationToken cancellationToken )
81+ private async Task CreateDbAsync ( CancellationToken cancellationToken )
8282 {
83- logger . LogInformation ( "Creating database..." ) ;
83+ _logger . LogInformation ( "Creating database..." ) ;
84+
85+ var dbConnection = MSGraphDbConnection ;
8486
85- logger . LogDebug ( "Dropping endpoints table..." ) ;
87+ _logger . LogDebug ( "Dropping endpoints table..." ) ;
8688 var dropTable = dbConnection . CreateCommand ( ) ;
8789 dropTable . CommandText = "DROP TABLE IF EXISTS endpoints" ;
8890 _ = await dropTable . ExecuteNonQueryAsync ( cancellationToken ) ;
8991
90- logger . LogDebug ( "Creating endpoints table..." ) ;
92+ _logger . LogDebug ( "Creating endpoints table..." ) ;
9193 var createTable = dbConnection . CreateCommand ( ) ;
9294 // when you change the schema, increase the db version number in ProxyUtils
9395 createTable . CommandText = "CREATE TABLE IF NOT EXISTS endpoints (path TEXT, graphVersion TEXT, hasSelect BOOLEAN)" ;
9496 _ = await createTable . ExecuteNonQueryAsync ( cancellationToken ) ;
9597
96- logger . LogDebug ( "Creating index on endpoints and version..." ) ;
98+ _logger . LogDebug ( "Creating index on endpoints and version..." ) ;
9799 // Add an index on the path and graphVersion columns
98100 var createIndex = dbConnection . CreateCommand ( ) ;
99101 createIndex . CommandText = "CREATE INDEX IF NOT EXISTS idx_endpoints_path_version ON endpoints (path, graphVersion)" ;
100102 _ = await createIndex . ExecuteNonQueryAsync ( cancellationToken ) ;
101103 }
102104
103- private static async Task FillDataAsync ( SqliteConnection dbConnection , ILogger logger , CancellationToken cancellationToken )
105+ private async Task FillDataAsync ( CancellationToken cancellationToken )
104106 {
105- logger . LogInformation ( "Filling database..." ) ;
107+ _logger . LogInformation ( "Filling database..." ) ;
108+
109+ var dbConnection = MSGraphDbConnection ;
106110
107111 var i = 0 ;
108112
@@ -113,7 +117,7 @@ private static async Task FillDataAsync(SqliteConnection dbConnection, ILogger l
113117 var graphVersion = openApiDocument . Key ;
114118 var document = openApiDocument . Value ;
115119
116- logger . LogDebug ( "Filling database for {GraphVersion}..." , graphVersion ) ;
120+ _logger . LogDebug ( "Filling database for {GraphVersion}..." , graphVersion ) ;
117121
118122 var insertEndpoint = dbConnection . CreateCommand ( ) ;
119123 insertEndpoint . CommandText = "INSERT INTO endpoints (path, graphVersion, hasSelect) VALUES (@path, @graphVersion, @hasSelect)" ;
@@ -125,20 +129,20 @@ private static async Task FillDataAsync(SqliteConnection dbConnection, ILogger l
125129 {
126130 cancellationToken . ThrowIfCancellationRequested ( ) ;
127131
128- logger . LogTrace ( "Endpoint {GraphVersion}{Key}..." , graphVersion , path . Key ) ;
132+ _logger . LogTrace ( "Endpoint {GraphVersion}{Key}..." , graphVersion , path . Key ) ;
129133
130134 // Get the GET operation for this path
131135 var getOperation = path . Value . Operations . FirstOrDefault ( o => o . Key == OperationType . Get ) . Value ;
132136 if ( getOperation == null )
133137 {
134- logger . LogTrace ( "No GET operation found for {GraphVersion}{Key}" , graphVersion , path . Key ) ;
138+ _logger . LogTrace ( "No GET operation found for {GraphVersion}{Key}" , graphVersion , path . Key ) ;
135139 continue ;
136140 }
137141
138142 // Check if the GET operation has a $select parameter
139143 var hasSelect = getOperation . Parameters . Any ( p => p . Name == "$select" ) ;
140144
141- logger . LogTrace ( "Inserting endpoint {GraphVersion}{Key} with hasSelect={HasSelect}..." , graphVersion , path . Key , hasSelect ) ;
145+ _logger . LogTrace ( "Inserting endpoint {GraphVersion}{Key} with hasSelect={HasSelect}..." , graphVersion , path . Key , hasSelect ) ;
142146 insertEndpoint . Parameters [ "@path" ] . Value = path . Key ;
143147 insertEndpoint . Parameters [ "@graphVersion" ] . Value = graphVersion ;
144148 insertEndpoint . Parameters [ "@hasSelect" ] . Value = hasSelect ;
@@ -147,54 +151,53 @@ private static async Task FillDataAsync(SqliteConnection dbConnection, ILogger l
147151 }
148152 }
149153
150- logger . LogInformation ( "Inserted {EndpointCount} endpoints in the database" , i ) ;
154+ _logger . LogInformation ( "Inserted {EndpointCount} endpoints in the database" , i ) ;
151155 }
152156
153- private static async Task UpdateOpenAPIGraphFilesIfNecessaryAsync ( string folder , ILogger logger , CancellationToken cancellationToken )
157+ private async Task UpdateOpenAPIGraphFilesIfNecessaryAsync ( string folder , CancellationToken cancellationToken )
154158 {
155- logger . LogInformation ( "Checking for updated OpenAPI files..." ) ;
159+ _logger . LogInformation ( "Checking for updated OpenAPI files..." ) ;
156160
157161 foreach ( var version in graphVersions )
158162 {
159163 try
160164 {
161165 var file = new FileInfo ( Path . Combine ( folder , GetGraphOpenApiYamlFileName ( version ) ) ) ;
162- logger . LogDebug ( "Checking for updated OpenAPI file {File}..." , file ) ;
166+ _logger . LogDebug ( "Checking for updated OpenAPI file {File}..." , file ) ;
163167 if ( file . Exists && file . LastWriteTime . Date == DateTime . Now . Date )
164168 {
165- logger . LogInformation ( "File {File} already updated today" , file ) ;
169+ _logger . LogInformation ( "File {File} already updated today" , file ) ;
166170 continue ;
167171 }
168172
169173 var url = $ "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/{ version } /openapi.yaml";
170- logger . LogInformation ( "Downloading OpenAPI file from {Url}..." , url ) ;
174+ _logger . LogInformation ( "Downloading OpenAPI file from {Url}..." , url ) ;
171175
172- using var client = new HttpClient ( ) ;
173- var response = await client . GetStringAsync ( url , cancellationToken ) ;
176+ var response = await _httpClient . GetStringAsync ( url , cancellationToken ) ;
174177 await File . WriteAllTextAsync ( file . FullName , response , cancellationToken ) ;
175178
176- logger . LogDebug ( "Downloaded OpenAPI file from {Url} to {File}" , url , file ) ;
179+ _logger . LogDebug ( "Downloaded OpenAPI file from {Url} to {File}" , url , file ) ;
177180 }
178181 catch ( Exception ex )
179182 {
180- logger . LogError ( ex , "Error updating OpenAPI files" ) ;
183+ _logger . LogError ( ex , "Error updating OpenAPI files" ) ;
181184 }
182185 }
183186 }
184187
185- private static async Task LoadOpenAPIFilesAsync ( string folder , ILogger logger , CancellationToken cancellationToken )
188+ private async Task LoadOpenAPIFilesAsync ( string folder , CancellationToken cancellationToken )
186189 {
187- logger . LogInformation ( "Loading OpenAPI files..." ) ;
190+ _logger . LogInformation ( "Loading OpenAPI files..." ) ;
188191
189192 foreach ( var version in graphVersions )
190193 {
191194 var filePath = Path . Combine ( folder , GetGraphOpenApiYamlFileName ( version ) ) ;
192195 var file = new FileInfo ( filePath ) ;
193- logger . LogDebug ( "Loading OpenAPI file for {FilePath}..." , filePath ) ;
196+ _logger . LogDebug ( "Loading OpenAPI file for {FilePath}..." , filePath ) ;
194197
195198 if ( ! file . Exists )
196199 {
197- logger . LogDebug ( "File {FilePath} does not exist" , filePath ) ;
200+ _logger . LogDebug ( "File {FilePath} does not exist" , filePath ) ;
198201 continue ;
199202 }
200203
@@ -203,12 +206,18 @@ private static async Task LoadOpenAPIFilesAsync(string folder, ILogger logger, C
203206 var openApiDocument = await new OpenApiStreamReader ( ) . ReadAsync ( file . OpenRead ( ) , cancellationToken ) ;
204207 _openApiDocuments [ version ] = openApiDocument . OpenApiDocument ;
205208
206- logger . LogDebug ( "Added OpenAPI file {FilePath} for {Version}" , filePath , version ) ;
209+ _logger . LogDebug ( "Added OpenAPI file {FilePath} for {Version}" , filePath , version ) ;
207210 }
208211 catch ( Exception ex )
209212 {
210- logger . LogError ( ex , "Error loading OpenAPI file {FilePath}" , filePath ) ;
213+ _logger . LogError ( ex , "Error loading OpenAPI file {FilePath}" , filePath ) ;
211214 }
212215 }
213216 }
217+
218+ public void Dispose ( )
219+ {
220+ _msGraphDbConnection ? . Dispose ( ) ;
221+ _httpClient ? . Dispose ( ) ;
222+ }
214223}
0 commit comments