mdan-cli 2.5.1 → 2.7.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/AGENTS.md +76 -1
- package/README.md +274 -4
- package/agents/auto-orchestrator.md +343 -0
- package/agents/devops.md +511 -94
- package/cli/mdan.py +111 -6
- package/cli/mdan_crewai.py +539 -0
- package/core/crewai_orchestrator.md +419 -0
- package/core/debate-protocol.md +454 -0
- package/core/universal-envelope.md +113 -0
- package/integrations/__init__.py +33 -0
- package/integrations/crewai/__init__.py +27 -0
- package/integrations/crewai/agents/__init__.py +21 -0
- package/integrations/crewai/agents/architect_agent.py +264 -0
- package/integrations/crewai/agents/dev_agent.py +271 -0
- package/integrations/crewai/agents/devops_agent.py +421 -0
- package/integrations/crewai/agents/doc_agent.py +388 -0
- package/integrations/crewai/agents/product_agent.py +203 -0
- package/integrations/crewai/agents/security_agent.py +386 -0
- package/integrations/crewai/agents/test_agent.py +358 -0
- package/integrations/crewai/agents/ux_agent.py +257 -0
- package/integrations/crewai/flows/__init__.py +13 -0
- package/integrations/crewai/flows/auto_flow.py +451 -0
- package/integrations/crewai/flows/build_flow.py +297 -0
- package/integrations/crewai/flows/debate_flow.py +422 -0
- package/integrations/crewai/flows/discovery_flow.py +267 -0
- package/integrations/crewai/orchestrator.py +558 -0
- package/integrations/crewai/skills/__init__.py +8 -0
- package/integrations/crewai/skills/skill_router.py +534 -0
- package/integrations/crewai/tools/__init__.py +11 -0
- package/integrations/crewai/tools/file_tool.py +355 -0
- package/integrations/crewai/tools/serper_tool.py +169 -0
- package/integrations/crewai/tools/sql_tool.py +435 -0
- package/memory/CONTEXT-SAVE-FORMAT.md +328 -0
- package/memory/MEMORY-AUTO.json +66 -0
- package/memory/RESUME-PROTOCOL.md +379 -0
- package/package.json +1 -1
- package/phases/auto-01-load.md +165 -0
- package/phases/auto-02-discover.md +207 -0
- package/phases/auto-03-plan.md +509 -0
- package/phases/auto-04-architect.md +567 -0
- package/phases/auto-05-implement.md +713 -0
- package/phases/auto-06-test.md +559 -0
- package/phases/auto-07-deploy.md +510 -0
- package/phases/auto-08-doc.md +970 -0
- package/skills/azure-devops/skill.md +1757 -0
- package/templates/dotnet-blazor/README.md +415 -0
- package/templates/external-services/ExampleService.cs +361 -0
- package/templates/external-services/IService.cs +113 -0
- package/templates/external-services/README.md +325 -0
- package/templates/external-services/ServiceBase.cs +492 -0
- package/templates/external-services/ServiceProvider.cs +243 -0
- package/templates/prompts/devops-agent.yaml +327 -0
- package/templates/prompts.json +15 -1
- package/templates/sql-server/README.md +37 -0
- package/templates/sql-server/functions.sql +158 -0
- package/templates/sql-server/schema.sql +188 -0
- package/templates/sql-server/stored-procedures.sql +284 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Threading.Tasks;
|
|
4
|
+
using Microsoft.Extensions.Configuration;
|
|
5
|
+
using Microsoft.Extensions.Logging;
|
|
6
|
+
|
|
7
|
+
namespace ExternalServices.Services
|
|
8
|
+
{
|
|
9
|
+
/// <summary>
|
|
10
|
+
/// Exemple complet d'implémentation d'un service externe.
|
|
11
|
+
///
|
|
12
|
+
/// Ce service exemple montre comment intégrer une API hypothétique "ApiExemple"
|
|
13
|
+
/// en utilisant le template ServiceProvider.
|
|
14
|
+
///
|
|
15
|
+
/// Fonctionnalités démontrées:
|
|
16
|
+
/// - Authentification avec token
|
|
17
|
+
/// - CRUD complet (Create, Read, Update, Delete)
|
|
18
|
+
/// - Recherche avec pagination
|
|
19
|
+
/// - Gestion des erreurs
|
|
20
|
+
/// - Utilisation des patterns (retry, circuit breaker, rate limiting, caching)
|
|
21
|
+
/// </summary>
|
|
22
|
+
public class ExampleService : ServiceBase
|
|
23
|
+
{
|
|
24
|
+
public ExampleService(
|
|
25
|
+
IConfiguration configuration,
|
|
26
|
+
ILogger<ExampleService> logger,
|
|
27
|
+
IMemoryCache? cache = null)
|
|
28
|
+
: base(configuration, "ExampleService", logger, cache)
|
|
29
|
+
{
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
#region Opérations CRUD
|
|
33
|
+
|
|
34
|
+
/// <summary>
|
|
35
|
+
/// Récupère un produit par son ID.
|
|
36
|
+
/// </summary>
|
|
37
|
+
/// <param name="productId">ID du produit.</param>
|
|
38
|
+
/// <returns>Informations du produit.</returns>
|
|
39
|
+
public async Task<ServiceResponse<Product>> GetProductAsync(int productId)
|
|
40
|
+
{
|
|
41
|
+
_logger.LogInformation("Fetching product {ProductId}", productId);
|
|
42
|
+
|
|
43
|
+
var response = await GetDataAsync<Product>($"products/{productId}");
|
|
44
|
+
|
|
45
|
+
if (response.Success)
|
|
46
|
+
{
|
|
47
|
+
_logger.LogInformation("Product {ProductId} fetched successfully", productId);
|
|
48
|
+
}
|
|
49
|
+
else
|
|
50
|
+
{
|
|
51
|
+
_logger.LogWarning("Failed to fetch product {ProductId}: {Error}",
|
|
52
|
+
productId, response.ErrorMessage);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return response;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// <summary>
|
|
59
|
+
/// Récupère la liste des produits avec pagination.
|
|
60
|
+
/// </summary>
|
|
61
|
+
/// <param name="page">Numéro de page (défaut: 1).</param>
|
|
62
|
+
/// <param name="pageSize">Taille de la page (défaut: 20).</param>
|
|
63
|
+
/// <param name="category">Filtre par catégorie (optionnel).</param>
|
|
64
|
+
/// <returns>Liste des produits.</returns>
|
|
65
|
+
public async Task<ServiceResponse<ProductListResponse>> GetProductsAsync(
|
|
66
|
+
int page = 1,
|
|
67
|
+
int pageSize = 20,
|
|
68
|
+
string? category = null)
|
|
69
|
+
{
|
|
70
|
+
_logger.LogInformation("Fetching products - Page: {Page}, Size: {PageSize}, Category: {Category}",
|
|
71
|
+
page, pageSize, category ?? "All");
|
|
72
|
+
|
|
73
|
+
var parameters = new Dictionary<string, string>
|
|
74
|
+
{
|
|
75
|
+
{ "page", page.ToString() },
|
|
76
|
+
{ "pageSize", pageSize.ToString() }
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
if (!string.IsNullOrEmpty(category))
|
|
80
|
+
{
|
|
81
|
+
parameters.Add("category", category);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
var response = await GetDataAsync<ProductListResponse>("products", parameters);
|
|
85
|
+
|
|
86
|
+
if (response.Success)
|
|
87
|
+
{
|
|
88
|
+
_logger.LogInformation("Fetched {Count} products", response.Data?.Items?.Count ?? 0);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return response;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/// <summary>
|
|
95
|
+
/// Crée un nouveau produit.
|
|
96
|
+
/// </summary>
|
|
97
|
+
/// <param name="request">Données du produit à créer.</param>
|
|
98
|
+
/// <returns>Produit créé avec son ID.</returns>
|
|
99
|
+
public async Task<ServiceResponse<ProductCreateResponse>> CreateProductAsync(CreateProductRequest request)
|
|
100
|
+
{
|
|
101
|
+
_logger.LogInformation("Creating product: {ProductName}", request.Name);
|
|
102
|
+
|
|
103
|
+
var response = await PostDataAsync<ProductCreateResponse>("products", request);
|
|
104
|
+
|
|
105
|
+
if (response.Success)
|
|
106
|
+
{
|
|
107
|
+
_logger.LogInformation("Product created successfully with ID: {ProductId}",
|
|
108
|
+
response.Data?.ProductId);
|
|
109
|
+
}
|
|
110
|
+
else
|
|
111
|
+
{
|
|
112
|
+
_logger.LogError("Failed to create product: {Error}", response.ErrorMessage);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return response;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/// <summary>
|
|
119
|
+
/// Met à jour un produit existant.
|
|
120
|
+
/// </summary>
|
|
121
|
+
/// <param name="productId">ID du produit à mettre à jour.</param>
|
|
122
|
+
/// <param name="request">Données de mise à jour.</param>
|
|
123
|
+
/// <returns>Résultat de la mise à jour.</returns>
|
|
124
|
+
public async Task<ServiceResponse<ProductUpdateResponse>> UpdateProductAsync(
|
|
125
|
+
int productId,
|
|
126
|
+
UpdateProductRequest request)
|
|
127
|
+
{
|
|
128
|
+
_logger.LogInformation("Updating product {ProductId}", productId);
|
|
129
|
+
|
|
130
|
+
var response = await PutDataAsync<ProductUpdateResponse>($"products/{productId}", request);
|
|
131
|
+
|
|
132
|
+
if (response.Success)
|
|
133
|
+
{
|
|
134
|
+
_logger.LogInformation("Product {ProductId} updated successfully", productId);
|
|
135
|
+
}
|
|
136
|
+
else
|
|
137
|
+
{
|
|
138
|
+
_logger.LogError("Failed to update product {ProductId}: {Error}",
|
|
139
|
+
productId, response.ErrorMessage);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return response;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/// <summary>
|
|
146
|
+
/// Supprime un produit.
|
|
147
|
+
/// </summary>
|
|
148
|
+
/// <param name="productId">ID du produit à supprimer.</param>
|
|
149
|
+
/// <returns>Résultat de la suppression.</returns>
|
|
150
|
+
public async Task<ServiceResponse<ProductDeleteResponse>> DeleteProductAsync(int productId)
|
|
151
|
+
{
|
|
152
|
+
_logger.LogInformation("Deleting product {ProductId}", productId);
|
|
153
|
+
|
|
154
|
+
var response = await DeleteDataAsync<ProductDeleteResponse>($"products/{productId}");
|
|
155
|
+
|
|
156
|
+
if (response.Success)
|
|
157
|
+
{
|
|
158
|
+
_logger.LogInformation("Product {ProductId} deleted successfully", productId);
|
|
159
|
+
}
|
|
160
|
+
else
|
|
161
|
+
{
|
|
162
|
+
_logger.LogError("Failed to delete product {ProductId}: {Error}",
|
|
163
|
+
productId, response.ErrorMessage);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return response;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
#endregion
|
|
170
|
+
|
|
171
|
+
#region Recherche
|
|
172
|
+
|
|
173
|
+
/// <summary>
|
|
174
|
+
/// Recherche des produits par terme de recherche.
|
|
175
|
+
/// </summary>
|
|
176
|
+
/// <param name="query">Terme de recherche.</param>
|
|
177
|
+
/// <param name="page">Numéro de page (défaut: 1).</param>
|
|
178
|
+
/// <param name="pageSize">Taille de la page (défaut: 20).</param>
|
|
179
|
+
/// <returns>Résultats de recherche.</returns>
|
|
180
|
+
public async Task<ServiceResponse<ProductListResponse>> SearchProductsAsync(
|
|
181
|
+
string query,
|
|
182
|
+
int page = 1,
|
|
183
|
+
int pageSize = 20)
|
|
184
|
+
{
|
|
185
|
+
_logger.LogInformation("Searching products with query: {Query}", query);
|
|
186
|
+
|
|
187
|
+
var parameters = new Dictionary<string, string>
|
|
188
|
+
{
|
|
189
|
+
{ "q", query },
|
|
190
|
+
{ "page", page.ToString() },
|
|
191
|
+
{ "pageSize", pageSize.ToString() }
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
var response = await GetDataAsync<ProductListResponse>("products/search", parameters);
|
|
195
|
+
|
|
196
|
+
if (response.Success)
|
|
197
|
+
{
|
|
198
|
+
_logger.LogInformation("Search returned {Count} results",
|
|
199
|
+
response.Data?.Items?.Count ?? 0);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return response;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
#endregion
|
|
206
|
+
|
|
207
|
+
#region Opérations Spécifiques
|
|
208
|
+
|
|
209
|
+
/// <summary>
|
|
210
|
+
/// Récupère les catégories de produits.
|
|
211
|
+
/// </summary>
|
|
212
|
+
/// <returns>Liste des catégories.</returns>
|
|
213
|
+
public async Task<ServiceResponse<List<Category>>> GetCategoriesAsync()
|
|
214
|
+
{
|
|
215
|
+
_logger.LogInformation("Fetching categories");
|
|
216
|
+
|
|
217
|
+
var response = await GetDataAsync<List<Category>>("categories");
|
|
218
|
+
|
|
219
|
+
if (response.Success)
|
|
220
|
+
{
|
|
221
|
+
_logger.LogInformation("Fetched {Count} categories", response.Data?.Count ?? 0);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return response;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/// <summary>
|
|
228
|
+
/// Récupère les statistiques des produits.
|
|
229
|
+
/// </summary>
|
|
230
|
+
/// <returns>Statistiques.</returns>
|
|
231
|
+
public async Task<ServiceResponse<ProductStatistics>> GetStatisticsAsync()
|
|
232
|
+
{
|
|
233
|
+
_logger.LogInformation("Fetching product statistics");
|
|
234
|
+
|
|
235
|
+
var response = await GetDataAsync<ProductStatistics>("products/statistics");
|
|
236
|
+
|
|
237
|
+
if (response.Success)
|
|
238
|
+
{
|
|
239
|
+
_logger.LogInformation("Statistics fetched: Total={Total}, Active={Active}",
|
|
240
|
+
response.Data?.TotalProducts, response.Data?.ActiveProducts);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return response;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
#endregion
|
|
247
|
+
|
|
248
|
+
#region Modèles de Données
|
|
249
|
+
|
|
250
|
+
/// <summary>
|
|
251
|
+
/// Modèle de produit.
|
|
252
|
+
/// </summary>
|
|
253
|
+
public class Product
|
|
254
|
+
{
|
|
255
|
+
public int Id { get; set; }
|
|
256
|
+
public string Name { get; set; } = string.Empty;
|
|
257
|
+
public string Description { get; set; } = string.Empty;
|
|
258
|
+
public decimal Price { get; set; }
|
|
259
|
+
public string Currency { get; set; } = "EUR";
|
|
260
|
+
public string Category { get; set; } = string.Empty;
|
|
261
|
+
public bool IsActive { get; set; }
|
|
262
|
+
public int Stock { get; set; }
|
|
263
|
+
public DateTime CreatedAt { get; set; }
|
|
264
|
+
public DateTime? UpdatedAt { get; set; }
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/// <summary>
|
|
268
|
+
/// Modèle de réponse de liste de produits.
|
|
269
|
+
/// </summary>
|
|
270
|
+
public class ProductListResponse
|
|
271
|
+
{
|
|
272
|
+
public List<Product> Items { get; set; } = new();
|
|
273
|
+
public int TotalCount { get; set; }
|
|
274
|
+
public int Page { get; set; }
|
|
275
|
+
public int PageSize { get; set; }
|
|
276
|
+
public int TotalPages { get; set; }
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/// <summary>
|
|
280
|
+
/// Modèle de requête pour créer un produit.
|
|
281
|
+
/// </summary>
|
|
282
|
+
public class CreateProductRequest
|
|
283
|
+
{
|
|
284
|
+
public string Name { get; set; } = string.Empty;
|
|
285
|
+
public string Description { get; set; } = string.Empty;
|
|
286
|
+
public decimal Price { get; set; }
|
|
287
|
+
public string Currency { get; set; } = "EUR";
|
|
288
|
+
public string Category { get; set; } = string.Empty;
|
|
289
|
+
public int Stock { get; set; }
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/// <summary>
|
|
293
|
+
/// Modèle de réponse de création de produit.
|
|
294
|
+
/// </summary>
|
|
295
|
+
public class ProductCreateResponse
|
|
296
|
+
{
|
|
297
|
+
public int ProductId { get; set; }
|
|
298
|
+
public bool Success { get; set; }
|
|
299
|
+
public string Message { get; set; } = string.Empty;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/// <summary>
|
|
303
|
+
/// Modèle de requête pour mettre à jour un produit.
|
|
304
|
+
/// </summary>
|
|
305
|
+
public class UpdateProductRequest
|
|
306
|
+
{
|
|
307
|
+
public string Name { get; set; } = string.Empty;
|
|
308
|
+
public string Description { get; set; } = string.Empty;
|
|
309
|
+
public decimal Price { get; set; }
|
|
310
|
+
public string Currency { get; set; } = "EUR";
|
|
311
|
+
public string Category { get; set; } = string.Empty;
|
|
312
|
+
public int Stock { get; set; }
|
|
313
|
+
public bool IsActive { get; set; }
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/// <summary>
|
|
317
|
+
/// Modèle de réponse de mise à jour de produit.
|
|
318
|
+
/// </summary>
|
|
319
|
+
public class ProductUpdateResponse
|
|
320
|
+
{
|
|
321
|
+
public bool Success { get; set; }
|
|
322
|
+
public string Message { get; set; } = string.Empty;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/// <summary>
|
|
326
|
+
/// Modèle de réponse de suppression de produit.
|
|
327
|
+
/// </summary>
|
|
328
|
+
public class ProductDeleteResponse
|
|
329
|
+
{
|
|
330
|
+
public bool Success { get; set; }
|
|
331
|
+
public string Message { get; set; } = string.Empty;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/// <summary>
|
|
335
|
+
/// Modèle de catégorie.
|
|
336
|
+
/// </summary>
|
|
337
|
+
public class Category
|
|
338
|
+
{
|
|
339
|
+
public string Id { get; set; } = string.Empty;
|
|
340
|
+
public string Name { get; set; } = string.Empty;
|
|
341
|
+
public string Description { get; set; } = string.Empty;
|
|
342
|
+
public int ProductCount { get; set; }
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/// <summary>
|
|
346
|
+
/// Modèle de statistiques de produits.
|
|
347
|
+
/// </summary>
|
|
348
|
+
public class ProductStatistics
|
|
349
|
+
{
|
|
350
|
+
public int TotalProducts { get; set; }
|
|
351
|
+
public int ActiveProducts { get; set; }
|
|
352
|
+
public int InactiveProducts { get; set; }
|
|
353
|
+
public decimal AveragePrice { get; set; }
|
|
354
|
+
public int TotalStock { get; set; }
|
|
355
|
+
public int LowStockProducts { get; set; }
|
|
356
|
+
public DateTime LastUpdated { get; set; }
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
#endregion
|
|
360
|
+
}
|
|
361
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Threading.Tasks;
|
|
4
|
+
|
|
5
|
+
namespace ExternalServices.Services
|
|
6
|
+
{
|
|
7
|
+
/// <summary>
|
|
8
|
+
/// Interface générique pour les services externes.
|
|
9
|
+
/// Fournit les opérations de base pour interagir avec n'importe quel service externe.
|
|
10
|
+
/// </summary>
|
|
11
|
+
public interface IService
|
|
12
|
+
{
|
|
13
|
+
/// <summary>
|
|
14
|
+
/// Nom du service.
|
|
15
|
+
/// </summary>
|
|
16
|
+
string ServiceName { get; }
|
|
17
|
+
|
|
18
|
+
/// <summary>
|
|
19
|
+
/// URL de base du service.
|
|
20
|
+
/// </summary>
|
|
21
|
+
string BaseUrl { get; }
|
|
22
|
+
|
|
23
|
+
/// <summary>
|
|
24
|
+
/// Authentifie le service auprès du fournisseur.
|
|
25
|
+
/// </summary>
|
|
26
|
+
/// <returns>Tâche asynchrone.</returns>
|
|
27
|
+
Task AuthenticateAsync();
|
|
28
|
+
|
|
29
|
+
/// <summary>
|
|
30
|
+
/// Vérifie si le service est authentifié.
|
|
31
|
+
/// </summary>
|
|
32
|
+
/// <returns>True si authentifié, false sinon.</returns>
|
|
33
|
+
Task<bool> IsAuthenticatedAsync();
|
|
34
|
+
|
|
35
|
+
/// <summary>
|
|
36
|
+
/// Récupère des données depuis un endpoint.
|
|
37
|
+
/// </summary>
|
|
38
|
+
/// <typeparam name="T">Type de données attendu.</typeparam>
|
|
39
|
+
/// <param name="endpoint">Endpoint à appeler.</param>
|
|
40
|
+
/// <param name="parameters">Paramètres de requête optionnels.</param>
|
|
41
|
+
/// <returns>Réponse du service.</returns>
|
|
42
|
+
Task<ServiceResponse<T>> GetDataAsync<T>(string endpoint, Dictionary<string, string>? parameters = null);
|
|
43
|
+
|
|
44
|
+
/// <summary>
|
|
45
|
+
/// Envoie des données à un endpoint via POST.
|
|
46
|
+
/// </summary>
|
|
47
|
+
/// <typeparam name="T">Type de réponse attendu.</typeparam>
|
|
48
|
+
/// <param name="endpoint">Endpoint à appeler.</param>
|
|
49
|
+
/// <param name="data">Données à envoyer.</param>
|
|
50
|
+
/// <returns>Réponse du service.</returns>
|
|
51
|
+
Task<ServiceResponse<T>> PostDataAsync<T>(string endpoint, object data);
|
|
52
|
+
|
|
53
|
+
/// <summary>
|
|
54
|
+
/// Met à jour des données via PUT.
|
|
55
|
+
/// </summary>
|
|
56
|
+
/// <typeparam name="T">Type de réponse attendu.</typeparam>
|
|
57
|
+
/// <param name="endpoint">Endpoint à appeler.</param>
|
|
58
|
+
/// <param name="data">Données à envoyer.</param>
|
|
59
|
+
/// <returns>Réponse du service.</returns>
|
|
60
|
+
Task<ServiceResponse<T>> PutDataAsync<T>(string endpoint, object data);
|
|
61
|
+
|
|
62
|
+
/// <summary>
|
|
63
|
+
/// Supprime des données via DELETE.
|
|
64
|
+
/// </summary>
|
|
65
|
+
/// <typeparam name="T">Type de réponse attendu.</typeparam>
|
|
66
|
+
/// <param name="endpoint">Endpoint à appeler.</param>
|
|
67
|
+
/// <returns>Réponse du service.</returns>
|
|
68
|
+
Task<ServiceResponse<T>> DeleteDataAsync<T>(string endpoint);
|
|
69
|
+
|
|
70
|
+
/// <summary>
|
|
71
|
+
/// Vérifie la santé du service.
|
|
72
|
+
/// </summary>
|
|
73
|
+
/// <returns>True si le service est sain, false sinon.</returns>
|
|
74
|
+
Task<bool> HealthCheckAsync();
|
|
75
|
+
|
|
76
|
+
/// <summary>
|
|
77
|
+
/// Récupère le statut détaillé du service.
|
|
78
|
+
/// </summary>
|
|
79
|
+
/// <returns>Statut du service.</returns>
|
|
80
|
+
Task<ServiceStatus> GetStatusAsync();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/// <summary>
|
|
84
|
+
/// Réponse générique d'un service externe.
|
|
85
|
+
/// </summary>
|
|
86
|
+
/// <typeparam name="T">Type des données.</typeparam>
|
|
87
|
+
public class ServiceResponse<T>
|
|
88
|
+
{
|
|
89
|
+
public bool Success { get; set; }
|
|
90
|
+
public T? Data { get; set; }
|
|
91
|
+
public string? ErrorCode { get; set; }
|
|
92
|
+
public string? ErrorMessage { get; set; }
|
|
93
|
+
public DateTime Timestamp { get; set; }
|
|
94
|
+
public int? StatusCode { get; set; }
|
|
95
|
+
public Dictionary<string, string>? Headers { get; set; }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/// <summary>
|
|
99
|
+
/// Statut d'un service externe.
|
|
100
|
+
/// </summary>
|
|
101
|
+
public class ServiceStatus
|
|
102
|
+
{
|
|
103
|
+
public bool IsHealthy { get; set; }
|
|
104
|
+
public bool IsAuthenticated { get; set; }
|
|
105
|
+
public bool IsCircuitOpen { get; set; }
|
|
106
|
+
public DateTime? LastSuccessfulCall { get; set; }
|
|
107
|
+
public DateTime? LastFailedCall { get; set; }
|
|
108
|
+
public int ConsecutiveFailures { get; set; }
|
|
109
|
+
public int TotalCalls { get; set; }
|
|
110
|
+
public int SuccessfulCalls { get; set; }
|
|
111
|
+
public int FailedCalls { get; set; }
|
|
112
|
+
}
|
|
113
|
+
}
|