django-cfg 1.5.8__py3-none-any.whl → 1.5.14__py3-none-any.whl

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.

Potentially problematic release.


This version of django-cfg might be problematic. Click here for more details.

Files changed (119) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/api/commands/serializers.py +152 -0
  3. django_cfg/apps/api/commands/views.py +32 -0
  4. django_cfg/apps/business/accounts/management/commands/otp_test.py +5 -2
  5. django_cfg/apps/business/agents/management/commands/create_agent.py +5 -194
  6. django_cfg/apps/business/agents/management/commands/load_agent_templates.py +205 -0
  7. django_cfg/apps/business/agents/management/commands/orchestrator_status.py +4 -2
  8. django_cfg/apps/business/knowbase/management/commands/knowbase_stats.py +4 -2
  9. django_cfg/apps/business/knowbase/management/commands/setup_knowbase.py +4 -2
  10. django_cfg/apps/business/newsletter/management/commands/test_newsletter.py +5 -2
  11. django_cfg/apps/business/payments/management/commands/check_payment_status.py +4 -2
  12. django_cfg/apps/business/payments/management/commands/create_payment.py +4 -2
  13. django_cfg/apps/business/payments/management/commands/sync_currencies.py +4 -2
  14. django_cfg/apps/integrations/centrifugo/management/commands/generate_centrifugo_clients.py +5 -5
  15. django_cfg/apps/integrations/centrifugo/serializers/__init__.py +2 -1
  16. django_cfg/apps/integrations/centrifugo/serializers/publishes.py +22 -2
  17. django_cfg/apps/integrations/centrifugo/views/monitoring.py +25 -40
  18. django_cfg/apps/integrations/grpc/admin/__init__.py +7 -1
  19. django_cfg/apps/integrations/grpc/admin/config.py +113 -9
  20. django_cfg/apps/integrations/grpc/admin/grpc_api_key.py +129 -0
  21. django_cfg/apps/integrations/grpc/admin/grpc_request_log.py +72 -63
  22. django_cfg/apps/integrations/grpc/admin/grpc_server_status.py +236 -0
  23. django_cfg/apps/integrations/grpc/auth/__init__.py +11 -3
  24. django_cfg/apps/integrations/grpc/auth/api_key_auth.py +320 -0
  25. django_cfg/apps/integrations/grpc/interceptors/logging.py +17 -20
  26. django_cfg/apps/integrations/grpc/interceptors/metrics.py +15 -14
  27. django_cfg/apps/integrations/grpc/interceptors/request_logger.py +79 -59
  28. django_cfg/apps/integrations/grpc/management/commands/generate_protos.py +130 -0
  29. django_cfg/apps/integrations/grpc/management/commands/rungrpc.py +171 -96
  30. django_cfg/apps/integrations/grpc/management/commands/test_grpc_integration.py +75 -0
  31. django_cfg/apps/integrations/grpc/managers/__init__.py +2 -0
  32. django_cfg/apps/integrations/grpc/managers/grpc_api_key.py +192 -0
  33. django_cfg/apps/integrations/grpc/managers/grpc_server_status.py +19 -11
  34. django_cfg/apps/integrations/grpc/migrations/0005_grpcapikey.py +143 -0
  35. django_cfg/apps/integrations/grpc/migrations/0006_grpcrequestlog_api_key_and_more.py +34 -0
  36. django_cfg/apps/integrations/grpc/models/__init__.py +2 -0
  37. django_cfg/apps/integrations/grpc/models/grpc_api_key.py +198 -0
  38. django_cfg/apps/integrations/grpc/models/grpc_request_log.py +11 -0
  39. django_cfg/apps/integrations/grpc/models/grpc_server_status.py +39 -4
  40. django_cfg/apps/integrations/grpc/serializers/__init__.py +22 -6
  41. django_cfg/apps/integrations/grpc/serializers/api_keys.py +63 -0
  42. django_cfg/apps/integrations/grpc/serializers/charts.py +118 -120
  43. django_cfg/apps/integrations/grpc/serializers/config.py +65 -51
  44. django_cfg/apps/integrations/grpc/serializers/health.py +7 -7
  45. django_cfg/apps/integrations/grpc/serializers/proto_files.py +74 -0
  46. django_cfg/apps/integrations/grpc/serializers/requests.py +13 -7
  47. django_cfg/apps/integrations/grpc/serializers/service_registry.py +181 -112
  48. django_cfg/apps/integrations/grpc/serializers/services.py +14 -32
  49. django_cfg/apps/integrations/grpc/serializers/stats.py +50 -12
  50. django_cfg/apps/integrations/grpc/serializers/testing.py +66 -58
  51. django_cfg/apps/integrations/grpc/services/__init__.py +2 -0
  52. django_cfg/apps/integrations/grpc/services/monitoring_service.py +149 -43
  53. django_cfg/apps/integrations/grpc/services/proto_files_manager.py +268 -0
  54. django_cfg/apps/integrations/grpc/services/service_registry.py +48 -46
  55. django_cfg/apps/integrations/grpc/services/testing_service.py +10 -15
  56. django_cfg/apps/integrations/grpc/urls.py +8 -0
  57. django_cfg/apps/integrations/grpc/utils/__init__.py +4 -13
  58. django_cfg/apps/integrations/grpc/utils/integration_test.py +334 -0
  59. django_cfg/apps/integrations/grpc/utils/proto_gen.py +48 -8
  60. django_cfg/apps/integrations/grpc/utils/streaming_logger.py +177 -0
  61. django_cfg/apps/integrations/grpc/views/__init__.py +4 -0
  62. django_cfg/apps/integrations/grpc/views/api_keys.py +255 -0
  63. django_cfg/apps/integrations/grpc/views/charts.py +21 -14
  64. django_cfg/apps/integrations/grpc/views/config.py +8 -6
  65. django_cfg/apps/integrations/grpc/views/monitoring.py +51 -79
  66. django_cfg/apps/integrations/grpc/views/proto_files.py +214 -0
  67. django_cfg/apps/integrations/grpc/views/services.py +30 -21
  68. django_cfg/apps/integrations/grpc/views/testing.py +45 -43
  69. django_cfg/apps/integrations/rq/views/jobs.py +19 -9
  70. django_cfg/apps/integrations/rq/views/schedule.py +7 -3
  71. django_cfg/apps/system/dashboard/serializers/commands.py +25 -1
  72. django_cfg/apps/system/dashboard/services/commands_service.py +12 -1
  73. django_cfg/apps/system/maintenance/management/commands/maintenance.py +5 -2
  74. django_cfg/apps/system/maintenance/management/commands/process_scheduled_maintenance.py +4 -2
  75. django_cfg/apps/system/maintenance/management/commands/sync_cloudflare.py +5 -2
  76. django_cfg/config.py +33 -0
  77. django_cfg/core/generation/integration_generators/grpc_generator.py +30 -32
  78. django_cfg/management/commands/check_endpoints.py +2 -2
  79. django_cfg/management/commands/check_settings.py +3 -10
  80. django_cfg/management/commands/clear_constance.py +3 -10
  81. django_cfg/management/commands/create_token.py +4 -11
  82. django_cfg/management/commands/list_urls.py +4 -10
  83. django_cfg/management/commands/migrate_all.py +18 -12
  84. django_cfg/management/commands/migrator.py +4 -11
  85. django_cfg/management/commands/script.py +4 -10
  86. django_cfg/management/commands/show_config.py +8 -16
  87. django_cfg/management/commands/show_urls.py +5 -11
  88. django_cfg/management/commands/superuser.py +4 -11
  89. django_cfg/management/commands/tree.py +5 -10
  90. django_cfg/management/utils/README.md +402 -0
  91. django_cfg/management/utils/__init__.py +29 -0
  92. django_cfg/management/utils/mixins.py +176 -0
  93. django_cfg/middleware/pagination.py +53 -54
  94. django_cfg/models/api/grpc/__init__.py +15 -21
  95. django_cfg/models/api/grpc/config.py +155 -73
  96. django_cfg/models/ngrok/config.py +7 -6
  97. django_cfg/modules/django_client/core/generator/python/files_generator.py +5 -13
  98. django_cfg/modules/django_client/core/generator/python/templates/api_wrapper.py.jinja +16 -4
  99. django_cfg/modules/django_client/core/generator/python/templates/main_init.py.jinja +2 -3
  100. django_cfg/modules/django_client/core/generator/typescript/files_generator.py +6 -5
  101. django_cfg/modules/django_client/core/generator/typescript/templates/main_index.ts.jinja +12 -8
  102. django_cfg/modules/django_client/core/parser/base.py +114 -30
  103. django_cfg/modules/django_client/management/commands/generate_client.py +5 -2
  104. django_cfg/modules/django_client/management/commands/validate_openapi.py +5 -2
  105. django_cfg/modules/django_email/management/commands/test_email.py +4 -10
  106. django_cfg/modules/django_ngrok/management/commands/runserver_ngrok.py +16 -13
  107. django_cfg/modules/django_telegram/management/commands/test_telegram.py +4 -11
  108. django_cfg/modules/django_twilio/management/commands/test_twilio.py +4 -11
  109. django_cfg/modules/django_unfold/navigation.py +6 -18
  110. django_cfg/pyproject.toml +1 -1
  111. django_cfg/registry/modules.py +1 -4
  112. django_cfg/requirements.txt +52 -0
  113. django_cfg/static/frontend/admin.zip +0 -0
  114. {django_cfg-1.5.8.dist-info → django_cfg-1.5.14.dist-info}/METADATA +1 -1
  115. {django_cfg-1.5.8.dist-info → django_cfg-1.5.14.dist-info}/RECORD +118 -97
  116. django_cfg/apps/integrations/grpc/auth/jwt_auth.py +0 -295
  117. {django_cfg-1.5.8.dist-info → django_cfg-1.5.14.dist-info}/WHEEL +0 -0
  118. {django_cfg-1.5.8.dist-info → django_cfg-1.5.14.dist-info}/entry_points.txt +0 -0
  119. {django_cfg-1.5.8.dist-info → django_cfg-1.5.14.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,268 @@
1
+ """
2
+ Proto Files Manager Service.
3
+
4
+ Handles proto file operations: scanning, reading, generating, archiving.
5
+ """
6
+
7
+ import io
8
+ import zipfile
9
+ from pathlib import Path
10
+ from typing import Dict, List, Optional
11
+
12
+ from django.conf import settings
13
+ from django_cfg.modules.django_logging import get_logger
14
+
15
+ from .config_helper import get_grpc_config
16
+
17
+ logger = get_logger("grpc.proto_files_manager")
18
+
19
+
20
+ class ProtoFilesManager:
21
+ """
22
+ Service for managing proto files.
23
+
24
+ Handles:
25
+ - Scanning proto directory
26
+ - Reading proto files
27
+ - Generating proto files from Django models
28
+ - Creating zip archives
29
+ """
30
+
31
+ def __init__(self):
32
+ """Initialize proto files manager."""
33
+ self.grpc_config = get_grpc_config()
34
+
35
+ def get_proto_dir(self) -> Path:
36
+ """
37
+ Get proto files directory path.
38
+
39
+ Returns:
40
+ Path to proto files directory
41
+ """
42
+ if self.grpc_config and self.grpc_config.proto and self.grpc_config.proto.output_dir:
43
+ proto_dir = Path(settings.BASE_DIR) / self.grpc_config.proto.output_dir
44
+ else:
45
+ proto_dir = Path(settings.MEDIA_ROOT) / "protos"
46
+
47
+ return proto_dir
48
+
49
+ def scan_proto_files(self, request=None) -> List[Dict]:
50
+ """
51
+ Scan proto directory and return list of proto files with metadata.
52
+
53
+ Args:
54
+ request: Optional Django request object for building download URLs
55
+
56
+ Returns:
57
+ List of dicts with proto file metadata:
58
+ {
59
+ "app_label": str,
60
+ "filename": str,
61
+ "size_bytes": int,
62
+ "package": str,
63
+ "messages_count": int,
64
+ "services_count": int,
65
+ "created_at": float,
66
+ "modified_at": float,
67
+ "download_url": str (if request provided),
68
+ }
69
+ """
70
+ proto_dir = self.get_proto_dir()
71
+
72
+ if not proto_dir.exists():
73
+ logger.warning(f"Proto directory does not exist: {proto_dir}")
74
+ return []
75
+
76
+ proto_files = []
77
+ for proto_file in proto_dir.glob("*.proto"):
78
+ try:
79
+ metadata = self._parse_proto_file(proto_file)
80
+ if metadata:
81
+ # Add download URL if request provided
82
+ if request:
83
+ from django.urls import reverse
84
+ from django_cfg.core.state import get_current_config
85
+
86
+ app_label = metadata['app_label']
87
+ config = get_current_config()
88
+
89
+ # Use api_url from config (respects HTTPS behind reverse proxy)
90
+ # Falls back to request.build_absolute_uri if config not available
91
+ if config and hasattr(config, 'api_url'):
92
+ path = reverse('django_cfg_grpc:proto-files-detail', kwargs={'pk': app_label})
93
+ download_url = f"{config.api_url}{path}"
94
+ else:
95
+ download_url = request.build_absolute_uri(
96
+ reverse('django_cfg_grpc:proto-files-detail', kwargs={'pk': app_label})
97
+ )
98
+
99
+ metadata['download_url'] = download_url
100
+
101
+ proto_files.append(metadata)
102
+ except Exception as e:
103
+ logger.error(f"Error reading proto file {proto_file}: {e}")
104
+ continue
105
+
106
+ return proto_files
107
+
108
+ def _parse_proto_file(self, proto_file: Path) -> Optional[Dict]:
109
+ """
110
+ Parse proto file and extract metadata.
111
+
112
+ Args:
113
+ proto_file: Path to proto file
114
+
115
+ Returns:
116
+ Dict with proto file metadata or None if failed
117
+ """
118
+ try:
119
+ stat = proto_file.stat()
120
+ content = proto_file.read_text()
121
+
122
+ # Parse proto file for metadata
123
+ package = ""
124
+ messages_count = 0
125
+ services_count = 0
126
+
127
+ for line in content.split("\n"):
128
+ line = line.strip()
129
+ if line.startswith("package "):
130
+ package = line.replace("package ", "").replace(";", "").strip()
131
+ elif line.startswith("message "):
132
+ messages_count += 1
133
+ elif line.startswith("service "):
134
+ services_count += 1
135
+
136
+ # Extract app_label from filename (crypto.proto -> crypto)
137
+ app_label = proto_file.stem
138
+
139
+ return {
140
+ "app_label": app_label,
141
+ "filename": proto_file.name,
142
+ "size_bytes": stat.st_size,
143
+ "package": package,
144
+ "messages_count": messages_count,
145
+ "services_count": services_count,
146
+ "created_at": stat.st_ctime,
147
+ "modified_at": stat.st_mtime,
148
+ }
149
+
150
+ except Exception as e:
151
+ logger.error(f"Error parsing proto file {proto_file}: {e}")
152
+ return None
153
+
154
+ def get_proto_file(self, app_label: str) -> Optional[Path]:
155
+ """
156
+ Get path to proto file for specific app.
157
+
158
+ Args:
159
+ app_label: App label (e.g., 'crypto')
160
+
161
+ Returns:
162
+ Path to proto file or None if not found
163
+ """
164
+ proto_dir = self.get_proto_dir()
165
+ proto_file = proto_dir / f"{app_label}.proto"
166
+
167
+ if proto_file.exists():
168
+ return proto_file
169
+
170
+ logger.warning(f"Proto file not found for app '{app_label}'")
171
+ return None
172
+
173
+ def create_zip_archive(self) -> Optional[bytes]:
174
+ """
175
+ Create zip archive with all proto files.
176
+
177
+ Returns:
178
+ Zip archive bytes or None if failed
179
+ """
180
+ proto_dir = self.get_proto_dir()
181
+
182
+ if not proto_dir.exists():
183
+ logger.error(f"Proto directory does not exist: {proto_dir}")
184
+ return None
185
+
186
+ try:
187
+ # Create zip in memory
188
+ zip_buffer = io.BytesIO()
189
+ with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file:
190
+ proto_files = list(proto_dir.glob("*.proto"))
191
+
192
+ if not proto_files:
193
+ logger.warning("No proto files found to archive")
194
+ return None
195
+
196
+ for proto_file in proto_files:
197
+ zip_file.write(proto_file, arcname=proto_file.name)
198
+ logger.debug(f"Added to archive: {proto_file.name}")
199
+
200
+ zip_buffer.seek(0)
201
+ return zip_buffer.read()
202
+
203
+ except Exception as e:
204
+ logger.error(f"Error creating zip archive: {e}", exc_info=True)
205
+ return None
206
+
207
+ def generate_protos(self, apps: Optional[List[str]] = None, force: bool = False) -> Dict:
208
+ """
209
+ Generate proto files for specified apps.
210
+
211
+ Args:
212
+ apps: List of app labels (uses enabled_apps from config if None)
213
+ force: Force regeneration even if proto file exists
214
+
215
+ Returns:
216
+ Dict with generation results:
217
+ {
218
+ "status": "success" | "failed",
219
+ "generated": List[str], # Successfully generated app labels
220
+ "generated_count": int,
221
+ "errors": List[Dict], # Errors for failed apps
222
+ }
223
+ """
224
+ from ..utils.proto_gen import generate_proto_for_app
225
+
226
+ # Determine which apps to generate for
227
+ if not apps:
228
+ if self.grpc_config and self.grpc_config.enabled_apps:
229
+ apps = self.grpc_config.enabled_apps
230
+ else:
231
+ logger.error("No apps specified and no enabled_apps in config")
232
+ return {
233
+ "status": "failed",
234
+ "generated": [],
235
+ "generated_count": 0,
236
+ "errors": [{"app": "N/A", "error": "No apps specified"}],
237
+ }
238
+
239
+ generated = []
240
+ errors = []
241
+
242
+ for app_label in apps:
243
+ try:
244
+ logger.info(f"Generating proto for app: {app_label}")
245
+ count = generate_proto_for_app(app_label)
246
+
247
+ if count > 0:
248
+ generated.append(app_label)
249
+ logger.info(f"Successfully generated proto for {app_label}")
250
+ else:
251
+ error_msg = "No models found"
252
+ logger.warning(f"No models found in app {app_label}")
253
+ errors.append({"app": app_label, "error": error_msg})
254
+
255
+ except Exception as e:
256
+ error_msg = str(e)
257
+ logger.error(f"Proto generation error for {app_label}: {error_msg}", exc_info=True)
258
+ errors.append({"app": app_label, "error": error_msg})
259
+
260
+ return {
261
+ "status": "success" if generated else "failed",
262
+ "generated": generated,
263
+ "generated_count": len(generated),
264
+ "errors": errors,
265
+ }
266
+
267
+
268
+ __all__ = ["ProtoFilesManager"]
@@ -11,11 +11,6 @@ from django.db import models
11
11
  from django.db.models import Avg, Count
12
12
 
13
13
  from ..models import GRPCRequestLog, GRPCServerStatus
14
- from ..serializers.service_registry import (
15
- MethodStatsSerializer,
16
- MethodSummarySerializer,
17
- ServiceSummarySerializer,
18
- )
19
14
  from django_cfg.modules.django_logging import get_logger
20
15
 
21
16
  logger = get_logger("grpc.service_registry")
@@ -52,7 +47,10 @@ class ServiceRegistryManager:
52
47
 
53
48
  def get_all_services(self) -> List[Dict]:
54
49
  """
55
- Get all registered services from the running gRPC server.
50
+ Get all registered services.
51
+
52
+ Returns services from running server if available,
53
+ otherwise discovers services from filesystem.
56
54
 
57
55
  Returns:
58
56
  List of service metadata dictionaries
@@ -66,11 +64,16 @@ class ServiceRegistryManager:
66
64
  'apps.CryptoService'
67
65
  """
68
66
  current_server = self.get_current_server()
69
- if not current_server:
70
- logger.debug("No running gRPC server found")
71
- return []
72
67
 
73
- return current_server.registered_services or []
68
+ # If server is running, use its registered services
69
+ if current_server and current_server.registered_services:
70
+ return current_server.registered_services
71
+
72
+ # Otherwise, discover services from filesystem
73
+ logger.debug("Server not running - discovering services from filesystem")
74
+ from .discovery import ServiceDiscovery
75
+ discovery = ServiceDiscovery()
76
+ return discovery.get_registered_services()
74
77
 
75
78
  def get_service_by_name(self, service_name: str) -> Optional[Dict]:
76
79
  """
@@ -183,23 +186,23 @@ class ServiceRegistryManager:
183
186
  # Extract package name
184
187
  package = service_name.split(".")[0] if "." in service_name else ""
185
188
 
186
- # Validate and serialize data
187
- service_summary = ServiceSummarySerializer(
188
- name=service_name,
189
- full_name=service.get("full_name", f"/{service_name}"),
190
- package=package,
191
- methods_count=len(service.get("methods", [])),
192
- total_requests=total,
193
- success_rate=round(success_rate, 2),
194
- avg_duration_ms=round(stats["avg_duration"] or 0, 2),
195
- last_activity_at=(
189
+ # Build dict directly
190
+ service_summary = {
191
+ "name": service_name,
192
+ "full_name": service.get("full_name", f"/{service_name}"),
193
+ "package": package,
194
+ "methods_count": len(service.get("methods", [])),
195
+ "total_requests": total,
196
+ "success_rate": round(success_rate, 2),
197
+ "avg_duration_ms": round(stats["avg_duration"] or 0, 2),
198
+ "last_activity_at": (
196
199
  stats["last_activity"].isoformat()
197
200
  if stats["last_activity"]
198
201
  else None
199
202
  ),
200
- )
203
+ }
201
204
 
202
- services_with_stats.append(service_summary.model_dump())
205
+ services_with_stats.append(service_summary)
203
206
 
204
207
  return services_with_stats
205
208
 
@@ -257,30 +260,29 @@ class ServiceRegistryManager:
257
260
  successful = stats["successful"] or 0
258
261
  success_rate = (successful / total * 100) if total > 0 else 0.0
259
262
 
260
- # Create stats object first
261
- method_stats = MethodStatsSerializer(
262
- service_name=service_name,
263
- method_name=method_name,
264
- total=total,
265
- successful=successful,
266
- errors=stats["errors"] or 0,
267
- avg_duration_ms=round(stats["avg_duration"] or 0, 2),
268
- p50_duration_ms=p50,
269
- p95_duration_ms=p95,
270
- p99_duration_ms=p99,
271
- )
272
-
273
- # Validate and serialize method with stats
274
- method_summary = MethodSummarySerializer(
275
- name=method_name,
276
- full_name=f"/{service_name}/{method_name}",
277
- service_name=service_name,
278
- request_type="",
279
- response_type="",
280
- stats=method_stats,
281
- )
282
-
283
- methods_list.append(method_summary.model_dump())
263
+ # Build method stats dict
264
+ method_stats = {
265
+ "total_requests": total,
266
+ "successful": successful,
267
+ "errors": stats["errors"] or 0,
268
+ "success_rate": round(success_rate, 2),
269
+ "avg_duration_ms": round(stats["avg_duration"] or 0, 2),
270
+ "p50_duration_ms": p50,
271
+ "p95_duration_ms": p95,
272
+ "p99_duration_ms": p99,
273
+ }
274
+
275
+ # Build method summary dict
276
+ method_summary = {
277
+ "name": method_name,
278
+ "full_name": f"/{service_name}/{method_name}",
279
+ "service_name": service_name,
280
+ "request_type": "",
281
+ "response_type": "",
282
+ "stats": method_stats,
283
+ }
284
+
285
+ methods_list.append(method_summary)
284
286
 
285
287
  return methods_list
286
288
 
@@ -11,11 +11,6 @@ from django.db.models import Count
11
11
  from django_cfg.modules.django_logging import get_logger
12
12
 
13
13
  from ..models import GRPCRequestLog
14
- from ..serializers.testing import (
15
- GRPCCallResponseSerializer,
16
- GRPCExampleSerializer,
17
- GRPCTestLogSerializer,
18
- )
19
14
  from ..testing import get_example
20
15
  from .service_registry import ServiceRegistryManager
21
16
 
@@ -75,18 +70,18 @@ class TestingService:
75
70
  # Get example from registry
76
71
  example_data = get_example(service_name, method_name)
77
72
  if example_data:
78
- # Validate and serialize
79
- example = GRPCExampleSerializer(
80
- service=service_name,
81
- method=method_name,
82
- description=example_data.get(
73
+ # Build dict directly
74
+ example = {
75
+ "service": service_name,
76
+ "method": method_name,
77
+ "description": example_data.get(
83
78
  "description", f"{method_name} method"
84
79
  ),
85
- request_example=example_data.get("request", {}),
86
- response_example=example_data.get("response", {}),
87
- notes=example_data.get("notes", ""),
88
- )
89
- examples.append(example.model_dump())
80
+ "payload_example": example_data.get("request", {}),
81
+ "expected_response": example_data.get("response", {}),
82
+ "metadata_example": example_data.get("metadata", {}),
83
+ }
84
+ examples.append(example)
90
85
 
91
86
  return examples
92
87
 
@@ -7,9 +7,11 @@ Public API endpoints for gRPC monitoring.
7
7
  from django.urls import include, path
8
8
  from rest_framework import routers
9
9
 
10
+ from .views.api_keys import GRPCApiKeyViewSet
10
11
  from .views.charts import GRPCChartsViewSet
11
12
  from .views.config import GRPCConfigViewSet
12
13
  from .views.monitoring import GRPCMonitorViewSet
14
+ from .views.proto_files import GRPCProtoFilesViewSet
13
15
  from .views.services import GRPCServiceViewSet
14
16
  from .views.testing import GRPCTestingViewSet
15
17
 
@@ -33,6 +35,12 @@ router.register(r'test', GRPCTestingViewSet, basename='test')
33
35
  # Charts endpoints (statistics visualization)
34
36
  router.register(r'charts', GRPCChartsViewSet, basename='charts')
35
37
 
38
+ # API Keys endpoints (read-only)
39
+ router.register(r'api-keys', GRPCApiKeyViewSet, basename='api-keys')
40
+
41
+ # Proto Files endpoints (download proto files)
42
+ router.register(r'proto-files', GRPCProtoFilesViewSet, basename='proto-files')
43
+
36
44
  urlpatterns = [
37
45
  # Include router URLs
38
46
  path('', include(router.urls)),
@@ -1,18 +1,9 @@
1
1
  """
2
- gRPC utilities.
2
+ Utilities for gRPC Integration.
3
3
 
4
- Provides proto generation and other helper utilities for gRPC integration.
5
-
6
- Note:
7
- For dependency checking, use `django_cfg.apps.integrations.grpc._cfg` instead.
8
- This module focuses on user-facing utilities like proto generation.
4
+ Reusable utilities for gRPC services in django-cfg.
9
5
  """
10
6
 
11
- from .proto_gen import ProtoFieldMapper, ProtoGenerator, generate_proto_for_app
7
+ from .streaming_logger import setup_streaming_logger, get_streaming_logger
12
8
 
13
- __all__ = [
14
- # Proto generation
15
- "ProtoFieldMapper",
16
- "ProtoGenerator",
17
- "generate_proto_for_app",
18
- ]
9
+ __all__ = ["setup_streaming_logger", "get_streaming_logger"]