django-cfg 1.4.10__py3-none-any.whl → 1.4.11__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.
- django_cfg/apps/agents/management/commands/create_agent.py +1 -1
- django_cfg/apps/agents/management/commands/orchestrator_status.py +3 -3
- django_cfg/apps/newsletter/serializers.py +40 -3
- django_cfg/apps/newsletter/views/campaigns.py +12 -3
- django_cfg/apps/newsletter/views/emails.py +14 -3
- django_cfg/apps/newsletter/views/subscriptions.py +12 -2
- django_cfg/apps/payments/views/api/currencies.py +49 -6
- django_cfg/apps/payments/views/api/webhooks.py +72 -7
- django_cfg/apps/payments/views/overview/serializers.py +34 -1
- django_cfg/apps/payments/views/overview/views.py +2 -1
- django_cfg/apps/payments/views/serializers/payments.py +6 -6
- django_cfg/apps/urls.py +106 -45
- django_cfg/core/base/config_model.py +2 -2
- django_cfg/core/constants.py +1 -1
- django_cfg/core/generation/integration_generators/__init__.py +1 -1
- django_cfg/core/generation/integration_generators/api.py +72 -49
- django_cfg/core/integration/display/startup.py +30 -22
- django_cfg/core/integration/url_integration.py +15 -16
- django_cfg/dashboard/sections/documentation.py +391 -0
- django_cfg/management/commands/check_endpoints.py +11 -160
- django_cfg/management/commands/check_settings.py +13 -348
- django_cfg/management/commands/clear_constance.py +13 -201
- django_cfg/management/commands/create_token.py +13 -321
- django_cfg/management/commands/generate_clients.py +23 -0
- django_cfg/management/commands/list_urls.py +13 -306
- django_cfg/management/commands/migrate_all.py +13 -126
- django_cfg/management/commands/migrator.py +13 -396
- django_cfg/management/commands/rundramatiq.py +15 -247
- django_cfg/management/commands/rundramatiq_simulator.py +12 -429
- django_cfg/management/commands/runserver_ngrok.py +15 -160
- django_cfg/management/commands/script.py +12 -488
- django_cfg/management/commands/show_config.py +12 -215
- django_cfg/management/commands/show_urls.py +12 -342
- django_cfg/management/commands/superuser.py +15 -295
- django_cfg/management/commands/task_clear.py +14 -217
- django_cfg/management/commands/task_status.py +13 -248
- django_cfg/management/commands/test_email.py +15 -86
- django_cfg/management/commands/test_telegram.py +14 -61
- django_cfg/management/commands/test_twilio.py +15 -105
- django_cfg/management/commands/tree.py +13 -383
- django_cfg/management/commands/validate_openapi.py +10 -0
- django_cfg/middleware/README.md +1 -1
- django_cfg/middleware/user_activity.py +3 -3
- django_cfg/models/__init__.py +2 -2
- django_cfg/models/api/drf/spectacular.py +6 -6
- django_cfg/models/django/__init__.py +2 -2
- django_cfg/models/django/openapi.py +238 -0
- django_cfg/modules/django_admin/management/__init__.py +0 -0
- django_cfg/modules/django_admin/management/commands/__init__.py +0 -0
- django_cfg/modules/django_admin/management/commands/check_endpoints.py +169 -0
- django_cfg/modules/django_admin/management/commands/check_settings.py +355 -0
- django_cfg/modules/django_admin/management/commands/clear_constance.py +208 -0
- django_cfg/modules/django_admin/management/commands/create_token.py +328 -0
- django_cfg/modules/django_admin/management/commands/list_urls.py +313 -0
- django_cfg/modules/django_admin/management/commands/migrate_all.py +133 -0
- django_cfg/modules/django_admin/management/commands/migrator.py +403 -0
- django_cfg/modules/django_admin/management/commands/script.py +496 -0
- django_cfg/modules/django_admin/management/commands/show_config.py +225 -0
- django_cfg/modules/django_admin/management/commands/show_urls.py +361 -0
- django_cfg/modules/django_admin/management/commands/superuser.py +302 -0
- django_cfg/modules/django_admin/management/commands/tree.py +390 -0
- django_cfg/modules/django_client/__init__.py +20 -0
- django_cfg/modules/django_client/apps.py +35 -0
- django_cfg/modules/django_client/core/__init__.py +56 -0
- django_cfg/modules/django_client/core/archive/__init__.py +11 -0
- django_cfg/modules/django_client/core/archive/manager.py +134 -0
- django_cfg/modules/django_client/core/cli/__init__.py +12 -0
- django_cfg/modules/django_client/core/cli/main.py +235 -0
- django_cfg/modules/django_client/core/config/__init__.py +18 -0
- django_cfg/modules/django_client/core/config/config.py +188 -0
- django_cfg/modules/django_client/core/config/group.py +101 -0
- django_cfg/modules/django_client/core/config/service.py +209 -0
- django_cfg/modules/django_client/core/generator/__init__.py +115 -0
- django_cfg/modules/django_client/core/generator/base.py +767 -0
- django_cfg/modules/django_client/core/generator/python.py +751 -0
- django_cfg/modules/django_client/core/generator/templates/python/__init__.py.jinja +9 -0
- django_cfg/modules/django_client/core/generator/templates/python/api_wrapper.py.jinja +130 -0
- django_cfg/modules/django_client/core/generator/templates/python/app_init.py.jinja +6 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/app_client.py.jinja +18 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/flat_client.py.jinja +38 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/main_client.py.jinja +50 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/main_client_file.py.jinja +13 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/operation_method.py.jinja +7 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/sub_client.py.jinja +11 -0
- django_cfg/modules/django_client/core/generator/templates/python/client_file.py.jinja +13 -0
- django_cfg/modules/django_client/core/generator/templates/python/main_init.py.jinja +50 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/app_models.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/enum_class.py.jinja +15 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/enums.py.jinja +8 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/models.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/schema_class.py.jinja +19 -0
- django_cfg/modules/django_client/core/generator/templates/python/utils/logger.py.jinja +255 -0
- django_cfg/modules/django_client/core/generator/templates/python/utils/schema.py.jinja +12 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/app_index.ts.jinja +2 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/app_client.ts.jinja +18 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/client.ts.jinja +327 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/flat_client.ts.jinja +109 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/main_client_file.ts.jinja +9 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/operation.ts.jinja +61 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/sub_client.ts.jinja +15 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client_file.ts.jinja +9 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/index.ts.jinja +5 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/main_index.ts.jinja +206 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/models/app_models.ts.jinja +8 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/models/enums.ts.jinja +4 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/models/models.ts.jinja +8 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/errors.ts.jinja +114 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/http.ts.jinja +98 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/logger.ts.jinja +251 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/schema.ts.jinja +7 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/storage.ts.jinja +114 -0
- django_cfg/modules/django_client/core/generator/typescript.py +872 -0
- django_cfg/modules/django_client/core/groups/__init__.py +13 -0
- django_cfg/modules/django_client/core/groups/detector.py +178 -0
- django_cfg/modules/django_client/core/groups/manager.py +314 -0
- django_cfg/modules/django_client/core/ir/__init__.py +57 -0
- django_cfg/modules/django_client/core/ir/context.py +387 -0
- django_cfg/modules/django_client/core/ir/operation.py +518 -0
- django_cfg/modules/django_client/core/ir/schema.py +353 -0
- django_cfg/modules/django_client/core/parser/__init__.py +74 -0
- django_cfg/modules/django_client/core/parser/base.py +648 -0
- django_cfg/modules/django_client/core/parser/models/__init__.py +74 -0
- django_cfg/modules/django_client/core/parser/models/base.py +212 -0
- django_cfg/modules/django_client/core/parser/models/components.py +160 -0
- django_cfg/modules/django_client/core/parser/models/openapi.py +203 -0
- django_cfg/modules/django_client/core/parser/models/operation.py +207 -0
- django_cfg/modules/django_client/core/parser/models/schema.py +266 -0
- django_cfg/modules/django_client/core/parser/openapi30.py +56 -0
- django_cfg/modules/django_client/core/parser/openapi31.py +64 -0
- django_cfg/modules/django_client/core/validation/__init__.py +22 -0
- django_cfg/modules/django_client/core/validation/checker.py +134 -0
- django_cfg/modules/django_client/core/validation/fixer.py +216 -0
- django_cfg/modules/django_client/core/validation/reporter.py +480 -0
- django_cfg/modules/django_client/core/validation/rules/__init__.py +11 -0
- django_cfg/modules/django_client/core/validation/rules/base.py +96 -0
- django_cfg/modules/django_client/core/validation/rules/type_hints.py +288 -0
- django_cfg/modules/django_client/core/validation/safety.py +266 -0
- django_cfg/modules/django_client/management/__init__.py +3 -0
- django_cfg/modules/django_client/management/commands/__init__.py +3 -0
- django_cfg/modules/django_client/management/commands/generate_client.py +422 -0
- django_cfg/modules/django_client/management/commands/validate_openapi.py +343 -0
- django_cfg/modules/django_client/spectacular/__init__.py +9 -0
- django_cfg/modules/django_client/spectacular/enum_naming.py +192 -0
- django_cfg/modules/django_client/urls.py +72 -0
- django_cfg/modules/django_email/management/__init__.py +0 -0
- django_cfg/modules/django_email/management/commands/__init__.py +0 -0
- django_cfg/modules/django_email/management/commands/test_email.py +93 -0
- django_cfg/modules/django_logging/django_logger.py +6 -6
- django_cfg/modules/django_ngrok/management/__init__.py +0 -0
- django_cfg/modules/django_ngrok/management/commands/__init__.py +0 -0
- django_cfg/modules/django_ngrok/management/commands/runserver_ngrok.py +167 -0
- django_cfg/modules/django_tasks/management/__init__.py +0 -0
- django_cfg/modules/django_tasks/management/commands/__init__.py +0 -0
- django_cfg/modules/django_tasks/management/commands/rundramatiq.py +254 -0
- django_cfg/modules/django_tasks/management/commands/rundramatiq_simulator.py +437 -0
- django_cfg/modules/django_tasks/management/commands/task_clear.py +226 -0
- django_cfg/modules/django_tasks/management/commands/task_status.py +257 -0
- django_cfg/modules/django_telegram/management/__init__.py +0 -0
- django_cfg/modules/django_telegram/management/commands/__init__.py +0 -0
- django_cfg/modules/django_telegram/management/commands/test_telegram.py +68 -0
- django_cfg/modules/django_twilio/management/__init__.py +0 -0
- django_cfg/modules/django_twilio/management/commands/__init__.py +0 -0
- django_cfg/modules/django_twilio/management/commands/test_twilio.py +112 -0
- django_cfg/modules/django_unfold/callbacks/main.py +16 -5
- django_cfg/modules/django_unfold/callbacks/revolution.py +41 -36
- django_cfg/pyproject.toml +2 -6
- django_cfg/registry/third_party.py +5 -7
- django_cfg/routing/callbacks.py +1 -1
- django_cfg/static/admin/css/prose-unfold.css +666 -0
- django_cfg/templates/admin/index.html +8 -0
- django_cfg/templates/admin/index_new.html +13 -0
- django_cfg/templates/admin/layouts/dashboard_with_tabs.html +15 -3
- django_cfg/templates/admin/sections/documentation_section.html +172 -0
- django_cfg/templates/admin/snippets/tabs/documentation_tab.html +231 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.11.dist-info}/METADATA +2 -2
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.11.dist-info}/RECORD +180 -59
- django_cfg/management/commands/generate.py +0 -107
- /django_cfg/models/django/{revolution.py → revolution_legacy.py} +0 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.11.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.11.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.11.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,238 @@
|
|
1
|
+
"""
|
2
|
+
Django Client (OpenAPI) Configuration with DRF Integration
|
3
|
+
|
4
|
+
Extended configuration model that integrates openapi_client for automatic
|
5
|
+
TypeScript and Python client generation from Django REST Framework endpoints.
|
6
|
+
|
7
|
+
This replaces django-revolution with a cleaner, faster, type-safe implementation.
|
8
|
+
"""
|
9
|
+
|
10
|
+
from typing import Dict, Any, Optional
|
11
|
+
from pydantic import BaseModel, Field
|
12
|
+
from django_cfg.modules.django_client.core.config import OpenAPIConfig, OpenAPIGroupConfig
|
13
|
+
|
14
|
+
|
15
|
+
class ExtendedOpenAPIConfig(OpenAPIConfig):
|
16
|
+
"""
|
17
|
+
Extended OpenAPI configuration with DRF parameters for django-cfg integration.
|
18
|
+
|
19
|
+
This extends the base OpenAPIConfig to include DRF-specific
|
20
|
+
parameters and django-cfg integration helpers.
|
21
|
+
|
22
|
+
Example:
|
23
|
+
```python
|
24
|
+
from django_cfg import ExtendedOpenAPIConfig, OpenAPIGroupConfig
|
25
|
+
|
26
|
+
config = ExtendedOpenAPIConfig(
|
27
|
+
enabled=True,
|
28
|
+
groups=[
|
29
|
+
OpenAPIGroupConfig(
|
30
|
+
name='api',
|
31
|
+
apps=['users', 'posts'],
|
32
|
+
title='Main API',
|
33
|
+
version='v1',
|
34
|
+
),
|
35
|
+
],
|
36
|
+
drf_title='My API',
|
37
|
+
drf_description='REST API for my project',
|
38
|
+
)
|
39
|
+
```
|
40
|
+
"""
|
41
|
+
|
42
|
+
# DRF Configuration parameters for automatic DRF setup
|
43
|
+
drf_title: str = Field(
|
44
|
+
default="API",
|
45
|
+
description="API title for DRF Spectacular"
|
46
|
+
)
|
47
|
+
drf_description: str = Field(
|
48
|
+
default="RESTful API",
|
49
|
+
description="API description for DRF Spectacular"
|
50
|
+
)
|
51
|
+
drf_version: str = Field(
|
52
|
+
default="1.0.0",
|
53
|
+
description="API version for DRF Spectacular"
|
54
|
+
)
|
55
|
+
drf_schema_path_prefix: Optional[str] = Field(
|
56
|
+
default=None, # Will default to "/api/" if None
|
57
|
+
description="Schema path prefix for DRF Spectacular"
|
58
|
+
)
|
59
|
+
drf_enable_browsable_api: bool = Field(
|
60
|
+
default=False,
|
61
|
+
description="Enable DRF browsable API"
|
62
|
+
)
|
63
|
+
drf_enable_throttling: bool = Field(
|
64
|
+
default=False,
|
65
|
+
description="Enable DRF throttling"
|
66
|
+
)
|
67
|
+
drf_serve_include_schema: bool = Field(
|
68
|
+
default=False,
|
69
|
+
description="Include schema in Spectacular UI"
|
70
|
+
)
|
71
|
+
|
72
|
+
# Django-cfg specific integration
|
73
|
+
api_prefix: str = Field(
|
74
|
+
default="api",
|
75
|
+
description="API prefix for URL routing (e.g., 'api' -> /api/...)"
|
76
|
+
)
|
77
|
+
|
78
|
+
def get_drf_schema_path_prefix(self) -> str:
|
79
|
+
"""Get the schema path prefix, defaulting to api_prefix if not set."""
|
80
|
+
if self.drf_schema_path_prefix:
|
81
|
+
return self.drf_schema_path_prefix
|
82
|
+
return f"/{self.api_prefix}/"
|
83
|
+
|
84
|
+
def get_drf_config_kwargs(self) -> Dict[str, Any]:
|
85
|
+
"""
|
86
|
+
Get kwargs for DRF configuration from this config.
|
87
|
+
|
88
|
+
Returns:
|
89
|
+
Dict of parameters for DRF + Spectacular setup
|
90
|
+
"""
|
91
|
+
return {
|
92
|
+
"title": self.drf_title,
|
93
|
+
"description": self.drf_description,
|
94
|
+
"version": self.drf_version,
|
95
|
+
"schema_path_prefix": self.get_drf_schema_path_prefix(),
|
96
|
+
"enable_browsable_api": self.drf_enable_browsable_api,
|
97
|
+
"enable_throttling": self.drf_enable_throttling,
|
98
|
+
"serve_include_schema": self.drf_serve_include_schema,
|
99
|
+
# REQUIRED by django-client for correct Request/Response split
|
100
|
+
"component_split_request": True,
|
101
|
+
"component_split_patch": True,
|
102
|
+
}
|
103
|
+
|
104
|
+
def get_groups_with_defaults(self) -> Dict[str, OpenAPIGroupConfig]:
|
105
|
+
"""
|
106
|
+
Get groups with django-cfg default groups automatically added.
|
107
|
+
|
108
|
+
Returns:
|
109
|
+
Dict of groups including default django-cfg groups
|
110
|
+
"""
|
111
|
+
# Convert list to dict for compatibility
|
112
|
+
groups_dict = {group.name: group for group in self.groups}
|
113
|
+
|
114
|
+
# Add default django-cfg groups if enabled
|
115
|
+
try:
|
116
|
+
from django_cfg.modules.base import BaseCfgModule
|
117
|
+
base_module = BaseCfgModule()
|
118
|
+
|
119
|
+
support_enabled = base_module.is_support_enabled()
|
120
|
+
accounts_enabled = base_module.is_accounts_enabled()
|
121
|
+
newsletter_enabled = base_module.is_newsletter_enabled()
|
122
|
+
leads_enabled = base_module.is_leads_enabled()
|
123
|
+
knowbase_enabled = base_module.is_knowbase_enabled()
|
124
|
+
agents_enabled = base_module.is_agents_enabled()
|
125
|
+
tasks_enabled = base_module.should_enable_tasks()
|
126
|
+
payments_enabled = base_module.is_payments_enabled()
|
127
|
+
|
128
|
+
# Collect all enabled django-cfg apps for unified group
|
129
|
+
enabled_cfg_apps = []
|
130
|
+
if support_enabled:
|
131
|
+
enabled_cfg_apps.append("django_cfg.apps.support")
|
132
|
+
if accounts_enabled:
|
133
|
+
enabled_cfg_apps.append("django_cfg.apps.accounts")
|
134
|
+
if newsletter_enabled:
|
135
|
+
enabled_cfg_apps.append("django_cfg.apps.newsletter")
|
136
|
+
if leads_enabled:
|
137
|
+
enabled_cfg_apps.append("django_cfg.apps.leads")
|
138
|
+
if knowbase_enabled:
|
139
|
+
enabled_cfg_apps.append("django_cfg.apps.knowbase")
|
140
|
+
if agents_enabled:
|
141
|
+
enabled_cfg_apps.append("django_cfg.apps.agents")
|
142
|
+
if tasks_enabled:
|
143
|
+
enabled_cfg_apps.append("django_cfg.apps.tasks")
|
144
|
+
if payments_enabled:
|
145
|
+
enabled_cfg_apps.append("django_cfg.apps.payments")
|
146
|
+
|
147
|
+
# Add unified 'cfg' group with all enabled apps
|
148
|
+
if enabled_cfg_apps and 'cfg' not in groups_dict:
|
149
|
+
groups_dict['cfg'] = OpenAPIGroupConfig(
|
150
|
+
name="cfg",
|
151
|
+
apps=enabled_cfg_apps,
|
152
|
+
title="Django-CFG API",
|
153
|
+
description="All django-cfg built-in applications",
|
154
|
+
)
|
155
|
+
|
156
|
+
# Skip individual cfg_* groups - use unified 'cfg' instead
|
157
|
+
return groups_dict
|
158
|
+
|
159
|
+
# Add Support group if enabled
|
160
|
+
if support_enabled and 'cfg_support' not in groups_dict:
|
161
|
+
groups_dict['cfg_support'] = OpenAPIGroupConfig(
|
162
|
+
name="cfg_support",
|
163
|
+
apps=["django_cfg.apps.support"],
|
164
|
+
title="Support API",
|
165
|
+
description="Support tickets and messages API",
|
166
|
+
)
|
167
|
+
|
168
|
+
# Add Accounts group if enabled
|
169
|
+
if accounts_enabled and 'cfg_accounts' not in groups_dict:
|
170
|
+
groups_dict['cfg_accounts'] = OpenAPIGroupConfig(
|
171
|
+
name="cfg_accounts",
|
172
|
+
apps=["django_cfg.apps.accounts"],
|
173
|
+
title="Accounts API",
|
174
|
+
description="User management, OTP, profiles, and activity tracking API",
|
175
|
+
)
|
176
|
+
|
177
|
+
# Add Newsletter group if enabled
|
178
|
+
if newsletter_enabled and 'cfg_newsletter' not in groups_dict:
|
179
|
+
groups_dict['cfg_newsletter'] = OpenAPIGroupConfig(
|
180
|
+
name="cfg_newsletter",
|
181
|
+
apps=["django_cfg.apps.newsletter"],
|
182
|
+
title="Newsletter API",
|
183
|
+
description="Email campaigns, subscriptions, and newsletter management API",
|
184
|
+
)
|
185
|
+
|
186
|
+
# Add Leads group if enabled
|
187
|
+
if leads_enabled and 'cfg_leads' not in groups_dict:
|
188
|
+
groups_dict['cfg_leads'] = OpenAPIGroupConfig(
|
189
|
+
name="cfg_leads",
|
190
|
+
apps=["django_cfg.apps.leads"],
|
191
|
+
title="Leads API",
|
192
|
+
description="Lead collection, contact forms, and CRM integration API",
|
193
|
+
)
|
194
|
+
|
195
|
+
# Add Knowbase group if enabled
|
196
|
+
if knowbase_enabled and 'cfg_knowbase' not in groups_dict:
|
197
|
+
groups_dict['cfg_knowbase'] = OpenAPIGroupConfig(
|
198
|
+
name="cfg_knowbase",
|
199
|
+
apps=["django_cfg.apps.knowbase"],
|
200
|
+
title="Knowbase API",
|
201
|
+
description="Knowledge base, AI chat, embeddings, and search API",
|
202
|
+
)
|
203
|
+
|
204
|
+
# Add Agents group if enabled
|
205
|
+
if agents_enabled and 'cfg_agents' not in groups_dict:
|
206
|
+
groups_dict['cfg_agents'] = OpenAPIGroupConfig(
|
207
|
+
name="cfg_agents",
|
208
|
+
apps=["django_cfg.apps.agents"],
|
209
|
+
title="Agents API",
|
210
|
+
description="Agent definitions, executions, workflows, and tools API",
|
211
|
+
)
|
212
|
+
|
213
|
+
# Add Tasks group if enabled
|
214
|
+
if tasks_enabled and 'cfg_tasks' not in groups_dict:
|
215
|
+
groups_dict['cfg_tasks'] = OpenAPIGroupConfig(
|
216
|
+
name="cfg_tasks",
|
217
|
+
apps=["django_cfg.apps.tasks"],
|
218
|
+
title="Tasks API",
|
219
|
+
description="Tasks, workflows, and automation API",
|
220
|
+
)
|
221
|
+
|
222
|
+
# Add Payments group if enabled
|
223
|
+
if payments_enabled and 'cfg_payments' not in groups_dict:
|
224
|
+
groups_dict['cfg_payments'] = OpenAPIGroupConfig(
|
225
|
+
name="cfg_payments",
|
226
|
+
apps=["django_cfg.apps.payments"],
|
227
|
+
title="Payments API",
|
228
|
+
description="Payments, subscriptions, and billing API",
|
229
|
+
)
|
230
|
+
|
231
|
+
except Exception:
|
232
|
+
pass
|
233
|
+
|
234
|
+
return groups_dict
|
235
|
+
|
236
|
+
|
237
|
+
# Alias for easier import
|
238
|
+
OpenAPIClientConfig = ExtendedOpenAPIConfig
|
File without changes
|
File without changes
|
@@ -0,0 +1,169 @@
|
|
1
|
+
"""
|
2
|
+
Django management command to check all API endpoints status.
|
3
|
+
|
4
|
+
Usage:
|
5
|
+
python manage.py check_endpoints
|
6
|
+
python manage.py check_endpoints --include-unnamed
|
7
|
+
python manage.py check_endpoints --timeout 10
|
8
|
+
python manage.py check_endpoints --json
|
9
|
+
"""
|
10
|
+
|
11
|
+
from django.core.management.base import BaseCommand
|
12
|
+
from django.urls import reverse
|
13
|
+
from django_cfg.apps.api.endpoints.checker import check_all_endpoints
|
14
|
+
import json
|
15
|
+
|
16
|
+
|
17
|
+
class Command(BaseCommand):
|
18
|
+
help = 'Check status of all Django CFG API endpoints'
|
19
|
+
|
20
|
+
def add_arguments(self, parser):
|
21
|
+
parser.add_argument(
|
22
|
+
'--include-unnamed',
|
23
|
+
action='store_true',
|
24
|
+
help='Include unnamed URL patterns in the check',
|
25
|
+
)
|
26
|
+
parser.add_argument(
|
27
|
+
'--timeout',
|
28
|
+
type=int,
|
29
|
+
default=5,
|
30
|
+
help='Request timeout in seconds (default: 5)',
|
31
|
+
)
|
32
|
+
parser.add_argument(
|
33
|
+
'--json',
|
34
|
+
action='store_true',
|
35
|
+
help='Output results as JSON',
|
36
|
+
)
|
37
|
+
parser.add_argument(
|
38
|
+
'--url',
|
39
|
+
type=str,
|
40
|
+
help='Check specific endpoint by URL name (e.g., "endpoints_status")',
|
41
|
+
)
|
42
|
+
parser.add_argument(
|
43
|
+
'--no-auth',
|
44
|
+
action='store_true',
|
45
|
+
help='Disable automatic JWT authentication retry (default: enabled)',
|
46
|
+
)
|
47
|
+
|
48
|
+
def handle(self, *args, **options):
|
49
|
+
include_unnamed = options['include_unnamed']
|
50
|
+
timeout = options['timeout']
|
51
|
+
output_json = options['json']
|
52
|
+
url_name = options.get('url')
|
53
|
+
auto_auth = not options['no_auth'] # Auto-auth enabled by default
|
54
|
+
|
55
|
+
# If specific URL requested, just resolve and display it
|
56
|
+
if url_name:
|
57
|
+
try:
|
58
|
+
url = reverse(url_name)
|
59
|
+
self.stdout.write(self.style.SUCCESS(f'✅ URL name "{url_name}" resolves to: {url}'))
|
60
|
+
return
|
61
|
+
except Exception as e:
|
62
|
+
self.stdout.write(self.style.ERROR(f'❌ Error resolving URL "{url_name}": {e}'))
|
63
|
+
return
|
64
|
+
|
65
|
+
# Check all endpoints
|
66
|
+
auth_msg = "with auto-auth" if auto_auth else "without auth"
|
67
|
+
self.stdout.write(self.style.WARNING(f'🔍 Checking endpoints (timeout: {timeout}s, {auth_msg})...'))
|
68
|
+
|
69
|
+
status_data = check_all_endpoints(
|
70
|
+
include_unnamed=include_unnamed,
|
71
|
+
timeout=timeout,
|
72
|
+
auto_auth=auto_auth
|
73
|
+
)
|
74
|
+
|
75
|
+
# Output as JSON if requested
|
76
|
+
if output_json:
|
77
|
+
self.stdout.write(json.dumps(status_data, indent=2))
|
78
|
+
return
|
79
|
+
|
80
|
+
# Pretty print results
|
81
|
+
self._print_results(status_data)
|
82
|
+
|
83
|
+
def _print_results(self, data):
|
84
|
+
"""Print formatted results to console."""
|
85
|
+
|
86
|
+
# Overall status
|
87
|
+
status = data['status']
|
88
|
+
if status == 'healthy':
|
89
|
+
status_style = self.style.SUCCESS
|
90
|
+
emoji = '✅'
|
91
|
+
elif status == 'degraded':
|
92
|
+
status_style = self.style.WARNING
|
93
|
+
emoji = '⚠️'
|
94
|
+
else:
|
95
|
+
status_style = self.style.ERROR
|
96
|
+
emoji = '❌'
|
97
|
+
|
98
|
+
self.stdout.write('')
|
99
|
+
self.stdout.write(status_style(f'{emoji} Overall Status: {status.upper()}'))
|
100
|
+
self.stdout.write('')
|
101
|
+
|
102
|
+
# Summary
|
103
|
+
self.stdout.write(self.style.HTTP_INFO('📊 Summary:'))
|
104
|
+
self.stdout.write(f' Total endpoints: {data["total_endpoints"]}')
|
105
|
+
self.stdout.write(self.style.SUCCESS(f' ✅ Healthy: {data["healthy"]}'))
|
106
|
+
self.stdout.write(self.style.WARNING(f' ⚠️ Warnings: {data["warnings"]}'))
|
107
|
+
self.stdout.write(self.style.ERROR(f' ❌ Unhealthy: {data["unhealthy"]}'))
|
108
|
+
self.stdout.write(self.style.ERROR(f' ❌ Errors: {data["errors"]}'))
|
109
|
+
self.stdout.write(f' ⏭️ Skipped: {data["skipped"]}')
|
110
|
+
self.stdout.write('')
|
111
|
+
|
112
|
+
# Endpoints details
|
113
|
+
self.stdout.write(self.style.HTTP_INFO('🔗 Endpoints:'))
|
114
|
+
|
115
|
+
for endpoint in data['endpoints']:
|
116
|
+
name = endpoint.get('url_name') or 'unnamed'
|
117
|
+
url = endpoint['url']
|
118
|
+
status = endpoint['status']
|
119
|
+
|
120
|
+
if status == 'healthy':
|
121
|
+
icon = '✅'
|
122
|
+
style = self.style.SUCCESS
|
123
|
+
elif status == 'degraded':
|
124
|
+
icon = '⚠️'
|
125
|
+
style = self.style.WARNING
|
126
|
+
else:
|
127
|
+
icon = '❌'
|
128
|
+
style = self.style.ERROR
|
129
|
+
|
130
|
+
self.stdout.write(f' {icon} {name}')
|
131
|
+
|
132
|
+
# Show both pattern and resolved URL for parametrized endpoints
|
133
|
+
if endpoint.get('has_parameters') and endpoint.get('url_pattern'):
|
134
|
+
self.stdout.write(f' Pattern: {endpoint["url_pattern"]}')
|
135
|
+
self.stdout.write(f' Resolved: {url}')
|
136
|
+
else:
|
137
|
+
self.stdout.write(f' URL: {url}')
|
138
|
+
|
139
|
+
# Show status with status code
|
140
|
+
status_code = endpoint.get('status_code')
|
141
|
+
if status_code:
|
142
|
+
self.stdout.write(style(f' Status: {status} ({status_code})'))
|
143
|
+
else:
|
144
|
+
self.stdout.write(style(f' Status: {status}'))
|
145
|
+
|
146
|
+
if endpoint.get('response_time_ms'):
|
147
|
+
self.stdout.write(f' Response time: {endpoint["response_time_ms"]:.2f}ms')
|
148
|
+
|
149
|
+
if endpoint.get('error'):
|
150
|
+
error_type = endpoint.get('error_type', 'general')
|
151
|
+
if error_type == 'database':
|
152
|
+
self.stdout.write(self.style.WARNING(f' ⚠️ DB Error (multi-db): {endpoint["error"]}'))
|
153
|
+
else:
|
154
|
+
self.stdout.write(self.style.ERROR(f' Error: {endpoint["error"]}'))
|
155
|
+
|
156
|
+
# Show reason for warnings (e.g., 404 explanations)
|
157
|
+
if endpoint.get('reason') and status == 'warning':
|
158
|
+
self.stdout.write(self.style.WARNING(f' ⚠️ {endpoint["reason"]}'))
|
159
|
+
|
160
|
+
if endpoint.get('required_auth'):
|
161
|
+
self.stdout.write(f' 🔐 Required JWT authentication')
|
162
|
+
|
163
|
+
if endpoint.get('rate_limited'):
|
164
|
+
self.stdout.write(f' ⏱️ Rate limited (429)')
|
165
|
+
|
166
|
+
self.stdout.write('')
|
167
|
+
|
168
|
+
# Timestamp
|
169
|
+
self.stdout.write(self.style.HTTP_INFO(f'🕐 Checked at: {data["timestamp"]}'))
|