django-cfg 1.4.11__py3-none-any.whl → 1.4.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.
- django_cfg/apps/urls.py +120 -108
- django_cfg/core/generation/integration_generators/api.py +2 -1
- django_cfg/core/integration/url_integration.py +5 -10
- django_cfg/models/django/openapi.py +15 -128
- django_cfg/modules/django_client/core/archive/manager.py +2 -2
- django_cfg/modules/django_client/core/config/config.py +20 -0
- django_cfg/modules/django_client/core/config/service.py +1 -1
- django_cfg/modules/django_client/core/generator/__init__.py +4 -4
- django_cfg/modules/django_client/core/generator/base.py +71 -0
- django_cfg/modules/django_client/core/generator/python/__init__.py +16 -0
- django_cfg/modules/django_client/core/generator/python/async_client_gen.py +174 -0
- django_cfg/modules/django_client/core/generator/python/files_generator.py +180 -0
- django_cfg/modules/django_client/core/generator/python/generator.py +182 -0
- django_cfg/modules/django_client/core/generator/python/models_generator.py +318 -0
- django_cfg/modules/django_client/core/generator/python/operations_generator.py +278 -0
- django_cfg/modules/django_client/core/generator/python/sync_client_gen.py +102 -0
- django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/api_wrapper.py.jinja +25 -2
- django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/client/main_client.py.jinja +24 -6
- django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/client/main_client_file.py.jinja +1 -0
- django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/client/operation_method.py.jinja +3 -1
- django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/client/sub_client.py.jinja +8 -1
- django_cfg/modules/django_client/core/generator/python/templates/client/sync_main_client.py.jinja +50 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/sync_operation_method.py.jinja +9 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/sync_sub_client.py.jinja +18 -0
- django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/main_init.py.jinja +2 -0
- django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/models/enum_class.py.jinja +3 -1
- django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/models/schema_class.py.jinja +3 -1
- django_cfg/modules/django_client/core/generator/python/templates/pyproject.toml.jinja +55 -0
- django_cfg/modules/django_client/core/generator/python/templates/utils/retry.py.jinja +271 -0
- django_cfg/modules/django_client/core/generator/typescript/__init__.py +14 -0
- django_cfg/modules/django_client/core/generator/typescript/client_generator.py +165 -0
- django_cfg/modules/django_client/core/generator/typescript/fetchers_generator.py +428 -0
- django_cfg/modules/django_client/core/generator/typescript/files_generator.py +207 -0
- django_cfg/modules/django_client/core/generator/typescript/generator.py +432 -0
- django_cfg/modules/django_client/core/generator/typescript/hooks_generator.py +539 -0
- django_cfg/modules/django_client/core/generator/typescript/models_generator.py +245 -0
- django_cfg/modules/django_client/core/generator/typescript/operations_generator.py +298 -0
- django_cfg/modules/django_client/core/generator/typescript/schemas_generator.py +329 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/api_instance.ts.jinja +131 -0
- django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/client/app_client.ts.jinja +1 -1
- django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/client/client.ts.jinja +77 -1
- django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/client/main_client_file.ts.jinja +1 -0
- django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/client/sub_client.ts.jinja +3 -3
- django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/fetchers.ts.jinja +45 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/index.ts.jinja +30 -0
- django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/main_index.ts.jinja +73 -11
- django_cfg/modules/django_client/core/generator/typescript/templates/package.json.jinja +52 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/schemas/index.ts.jinja +21 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/schemas/schema.ts.jinja +24 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/tsconfig.json.jinja +20 -0
- django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/utils/errors.ts.jinja +3 -1
- django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/utils/logger.ts.jinja +9 -1
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/retry.ts.jinja +175 -0
- django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/utils/storage.ts.jinja +54 -10
- django_cfg/modules/django_client/management/commands/generate_client.py +5 -0
- django_cfg/modules/django_client/pytest.ini +30 -0
- django_cfg/modules/django_client/spectacular/__init__.py +3 -2
- django_cfg/modules/django_client/spectacular/async_detection.py +187 -0
- django_cfg/{dashboard → modules/django_dashboard}/management/commands/debug_dashboard.py +5 -5
- django_cfg/modules/django_logging/LOGGING_GUIDE.md +1 -1
- django_cfg/modules/django_unfold/callbacks/main.py +6 -6
- django_cfg/modules/django_unfold/dashboard.py +6 -6
- django_cfg/pyproject.toml +1 -1
- {django_cfg-1.4.11.dist-info → django_cfg-1.4.14.dist-info}/METADATA +1 -1
- {django_cfg-1.4.11.dist-info → django_cfg-1.4.14.dist-info}/RECORD +100 -78
- django_cfg/dashboard/DEBUG_README.md +0 -105
- django_cfg/dashboard/REFACTORING_SUMMARY.md +0 -237
- django_cfg/modules/django_client/core/generator/python.py +0 -751
- django_cfg/modules/django_client/core/generator/typescript.py +0 -872
- django_cfg/modules/django_drf_theme/CHANGELOG.md +0 -210
- django_cfg/modules/django_drf_theme/EXAMPLE.md +0 -465
- django_cfg/modules/django_drf_theme/IMPLEMENTATION.md +0 -232
- django_cfg/modules/django_drf_theme/README.md +0 -207
- django_cfg/modules/django_drf_theme/TAILWIND_CDN_GUIDE.md +0 -274
- /django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/__init__.py.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/app_init.py.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/client/app_client.py.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/client/flat_client.py.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/client_file.py.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/models/app_models.py.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/models/enums.py.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/models/models.py.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/utils/logger.py.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/python → python/templates}/utils/schema.py.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/app_index.ts.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/client/flat_client.ts.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/client/operation.ts.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/client_file.ts.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/index.ts.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/models/app_models.ts.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/models/enums.ts.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/models/models.ts.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/utils/http.ts.jinja +0 -0
- /django_cfg/modules/django_client/core/generator/{templates/typescript → typescript/templates}/utils/schema.ts.jinja +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/__init__.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/components.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/debug.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/management/__init__.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/management/commands/__init__.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/__init__.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/base.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/commands.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/documentation.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/overview.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/stats.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/system.py +0 -0
- {django_cfg-1.4.11.dist-info → django_cfg-1.4.14.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.11.dist-info → django_cfg-1.4.14.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.11.dist-info → django_cfg-1.4.14.dist-info}/licenses/LICENSE +0 -0
django_cfg/apps/urls.py
CHANGED
@@ -5,130 +5,142 @@ Built-in API endpoints for django_cfg functionality.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
from django.urls import path, include
|
8
|
-
from typing import List
|
9
|
-
from django.urls import URLPattern
|
8
|
+
from typing import List
|
10
9
|
|
11
10
|
|
12
|
-
def
|
11
|
+
def get_enabled_cfg_apps() -> List[str]:
|
13
12
|
"""
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
Args:
|
19
|
-
patterns: URL patterns list to append to
|
20
|
-
groups: OpenAPI groups dict
|
21
|
-
"""
|
22
|
-
for group_name in groups.keys():
|
23
|
-
# Only django-cfg apps (convention: cfg_*)
|
24
|
-
if not group_name.startswith('cfg_'):
|
25
|
-
continue
|
26
|
-
|
27
|
-
# Extract app name: cfg_payments → payments
|
28
|
-
app_name = group_name[4:]
|
29
|
-
|
30
|
-
# Register main URLs: /cfg/{app}/
|
31
|
-
try:
|
32
|
-
patterns.append(
|
33
|
-
path(f'cfg/{app_name}/', include(f'django_cfg.apps.{app_name}.urls'))
|
34
|
-
)
|
35
|
-
except ImportError:
|
36
|
-
pass # URL module doesn't exist
|
37
|
-
|
38
|
-
# Register admin URLs: /cfg/{app}/admin/ (if exists)
|
39
|
-
try:
|
40
|
-
patterns.append(
|
41
|
-
path(f'cfg/{app_name}/admin/', include(f'django_cfg.apps.{app_name}.urls_admin'))
|
42
|
-
)
|
43
|
-
except ImportError:
|
44
|
-
pass # Admin URL module doesn't exist
|
45
|
-
|
46
|
-
|
47
|
-
def _register_apps_fallback(patterns: List[URLPattern]) -> None:
|
48
|
-
"""
|
49
|
-
Fallback: Register apps when OpenAPI is disabled.
|
50
|
-
|
51
|
-
Uses BaseCfgModule checks to determine which apps are enabled.
|
52
|
-
|
53
|
-
Args:
|
54
|
-
patterns: URL patterns list to append to
|
13
|
+
Get list of enabled django-cfg apps based on configuration.
|
14
|
+
|
15
|
+
Returns:
|
16
|
+
List of enabled app paths (e.g., ['django_cfg.apps.accounts', ...])
|
55
17
|
"""
|
56
18
|
from django_cfg.modules.base import BaseCfgModule
|
19
|
+
|
57
20
|
base_module = BaseCfgModule()
|
58
|
-
|
59
|
-
|
60
|
-
if base_module.is_support_enabled():
|
61
|
-
patterns.append(path('cfg/support/', include('django_cfg.apps.support.urls')))
|
62
|
-
|
21
|
+
enabled_apps = []
|
22
|
+
|
63
23
|
if base_module.is_accounts_enabled():
|
64
|
-
|
65
|
-
|
24
|
+
enabled_apps.append("django_cfg.apps.accounts")
|
25
|
+
|
26
|
+
if base_module.is_support_enabled():
|
27
|
+
enabled_apps.append("django_cfg.apps.support")
|
28
|
+
|
66
29
|
if base_module.is_newsletter_enabled():
|
67
|
-
|
68
|
-
|
30
|
+
enabled_apps.append("django_cfg.apps.newsletter")
|
31
|
+
|
69
32
|
if base_module.is_leads_enabled():
|
70
|
-
|
71
|
-
|
33
|
+
enabled_apps.append("django_cfg.apps.leads")
|
34
|
+
|
72
35
|
if base_module.is_knowbase_enabled():
|
73
|
-
|
74
|
-
|
36
|
+
enabled_apps.append("django_cfg.apps.knowbase")
|
37
|
+
|
75
38
|
if base_module.is_agents_enabled():
|
76
|
-
|
77
|
-
|
39
|
+
enabled_apps.append("django_cfg.apps.agents")
|
40
|
+
|
78
41
|
if base_module.should_enable_tasks():
|
79
|
-
|
80
|
-
|
81
|
-
|
42
|
+
enabled_apps.append("django_cfg.apps.tasks")
|
43
|
+
|
82
44
|
if base_module.is_payments_enabled():
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
# Standalone apps
|
87
|
-
if base_module.is_maintenance_enabled():
|
88
|
-
patterns.append(
|
89
|
-
path('admin/django_cfg_maintenance/', include('django_cfg.apps.maintenance.urls_admin'))
|
90
|
-
)
|
91
|
-
|
92
|
-
if base_module.is_rpc_enabled():
|
93
|
-
patterns.append(path('rpc/', include('django_cfg.modules.django_ipc_client.dashboard.urls')))
|
94
|
-
patterns.append(path('admin/rpc/', include('django_cfg.modules.django_ipc_client.dashboard.urls_admin')))
|
45
|
+
enabled_apps.append("django_cfg.apps.payments")
|
46
|
+
|
47
|
+
return enabled_apps
|
95
48
|
|
96
49
|
|
97
|
-
def
|
50
|
+
def get_default_cfg_group():
|
98
51
|
"""
|
99
|
-
|
100
|
-
|
52
|
+
Returns default OpenAPIGroupConfig for enabled django-cfg apps.
|
53
|
+
|
54
|
+
Only includes apps that are enabled in the current configuration.
|
55
|
+
|
56
|
+
This can be imported and added to your project's OpenAPIClientConfig groups:
|
57
|
+
|
58
|
+
```python
|
59
|
+
from django_cfg.apps.urls import get_default_cfg_group
|
60
|
+
|
61
|
+
openapi_client = OpenAPIClientConfig(
|
62
|
+
groups=[
|
63
|
+
get_default_cfg_group(),
|
64
|
+
# ... your custom groups
|
65
|
+
]
|
66
|
+
)
|
67
|
+
```
|
68
|
+
|
101
69
|
Returns:
|
102
|
-
|
70
|
+
OpenAPIGroupConfig with enabled django-cfg apps
|
103
71
|
"""
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
72
|
+
from django_cfg.modules.django_client.core.config import OpenAPIGroupConfig
|
73
|
+
|
74
|
+
return OpenAPIGroupConfig(
|
75
|
+
name="cfg",
|
76
|
+
apps=get_enabled_cfg_apps(),
|
77
|
+
title="Django-CFG API",
|
78
|
+
description="Authentication (OTP), Support, Newsletter, Leads, Knowledge Base, AI Agents, Tasks, Payments",
|
79
|
+
version="1.0.0",
|
80
|
+
)
|
81
|
+
|
82
|
+
|
83
|
+
def _safe_include(pattern_path: str, module_path: str):
|
84
|
+
"""Helper to safely include URL module if it exists."""
|
115
85
|
try:
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
86
|
+
return path(pattern_path, include(module_path))
|
87
|
+
except ImportError:
|
88
|
+
return None
|
89
|
+
|
90
|
+
|
91
|
+
# Core API endpoints (always enabled)
|
92
|
+
# Note: All prefixes are explicit here (cfg/, health/, etc.)
|
93
|
+
urlpatterns = [
|
94
|
+
path('cfg/health/', include('django_cfg.apps.api.health.urls')),
|
95
|
+
path('cfg/endpoints/', include('django_cfg.apps.api.endpoints.urls')),
|
96
|
+
path('cfg/commands/', include('django_cfg.apps.api.commands.urls')),
|
97
|
+
path('cfg/openapi/', include('django_cfg.modules.django_client.urls')),
|
98
|
+
]
|
99
|
+
|
100
|
+
# Django-CFG apps - conditionally registered based on config
|
101
|
+
# Map app paths to URL patterns (with cfg/ prefix from add_django_cfg_urls)
|
102
|
+
APP_URL_MAP = {
|
103
|
+
"django_cfg.apps.accounts": [
|
104
|
+
("cfg/accounts/", "django_cfg.apps.accounts.urls"),
|
105
|
+
],
|
106
|
+
"django_cfg.apps.support": [
|
107
|
+
("cfg/support/", "django_cfg.apps.support.urls"),
|
108
|
+
],
|
109
|
+
"django_cfg.apps.newsletter": [
|
110
|
+
("cfg/newsletter/", "django_cfg.apps.newsletter.urls"),
|
111
|
+
],
|
112
|
+
"django_cfg.apps.leads": [
|
113
|
+
("cfg/leads/", "django_cfg.apps.leads.urls"),
|
114
|
+
],
|
115
|
+
"django_cfg.apps.knowbase": [
|
116
|
+
("cfg/knowbase/", "django_cfg.apps.knowbase.urls"),
|
117
|
+
],
|
118
|
+
"django_cfg.apps.agents": [
|
119
|
+
("cfg/agents/", "django_cfg.apps.agents.urls"),
|
120
|
+
],
|
121
|
+
"django_cfg.apps.tasks": [
|
122
|
+
("cfg/tasks/", "django_cfg.apps.tasks.urls"),
|
123
|
+
("cfg/tasks/admin/", "django_cfg.apps.tasks.urls_admin"),
|
124
|
+
],
|
125
|
+
"django_cfg.apps.payments": [
|
126
|
+
("cfg/payments/", "django_cfg.apps.payments.urls"),
|
127
|
+
("cfg/payments/admin/", "django_cfg.apps.payments.urls_admin"),
|
128
|
+
],
|
129
|
+
}
|
130
|
+
|
131
|
+
# Register URLs for enabled apps only
|
132
|
+
enabled_apps = get_enabled_cfg_apps()
|
133
|
+
cfg_app_urls = []
|
134
|
+
|
135
|
+
for app_path in enabled_apps:
|
136
|
+
if app_path in APP_URL_MAP:
|
137
|
+
for url_pattern, url_module in APP_URL_MAP[app_path]:
|
138
|
+
cfg_app_urls.append(_safe_include(url_pattern, url_module))
|
139
|
+
|
140
|
+
# Maintenance (special case - admin only)
|
141
|
+
from django_cfg.modules.base import BaseCfgModule
|
142
|
+
if BaseCfgModule().is_maintenance_enabled():
|
143
|
+
cfg_app_urls.append(_safe_include('admin/django_cfg_maintenance/', 'django_cfg.apps.maintenance.urls_admin'))
|
144
|
+
|
145
|
+
# Add only successfully imported URLs
|
146
|
+
urlpatterns.extend([url for url in cfg_app_urls if url is not None])
|
@@ -152,9 +152,10 @@ class APIFrameworksGenerator:
|
|
152
152
|
},
|
153
153
|
"COMPONENT_SPLIT_REQUEST": True,
|
154
154
|
"COMPONENT_SPLIT_PATCH": True,
|
155
|
-
#
|
155
|
+
# Postprocessing hooks
|
156
156
|
"POSTPROCESSING_HOOKS": [
|
157
157
|
"django_cfg.modules.django_client.spectacular.auto_fix_enum_names",
|
158
|
+
"django_cfg.modules.django_client.spectacular.mark_async_operations",
|
158
159
|
],
|
159
160
|
}
|
160
161
|
|
@@ -10,18 +10,17 @@ from django_cfg.core.environment import EnvironmentDetector
|
|
10
10
|
from django.conf import settings
|
11
11
|
|
12
12
|
|
13
|
-
def add_django_cfg_urls(urlpatterns: List[URLPattern]
|
13
|
+
def add_django_cfg_urls(urlpatterns: List[URLPattern]) -> List[URLPattern]:
|
14
14
|
"""
|
15
15
|
Automatically add django_cfg URLs and all integrations to the main URL configuration.
|
16
16
|
|
17
17
|
This function adds:
|
18
|
-
- Django CFG management URLs
|
18
|
+
- Django CFG management URLs
|
19
19
|
- Django Client URLs (if available)
|
20
20
|
- Startup information display (based on config)
|
21
21
|
|
22
22
|
Args:
|
23
23
|
urlpatterns: Existing URL patterns list
|
24
|
-
cfg_prefix: URL prefix for django_cfg endpoints (default: "cfg/")
|
25
24
|
|
26
25
|
Returns:
|
27
26
|
Updated URL patterns list with all URLs added
|
@@ -35,17 +34,13 @@ def add_django_cfg_urls(urlpatterns: List[URLPattern], cfg_prefix: str = "cfg/")
|
|
35
34
|
path("admin/", admin.site.urls),
|
36
35
|
]
|
37
36
|
|
38
|
-
# Automatically adds
|
39
|
-
# - path("cfg/", include("django_cfg.apps.urls"))
|
40
|
-
# - Django Client URLs (if available)
|
41
|
-
# - Startup info display (based on config.startup_info_mode)
|
37
|
+
# Automatically adds django_cfg URLs with proper prefixes
|
42
38
|
urlpatterns = add_django_cfg_urls(urlpatterns)
|
43
39
|
"""
|
44
40
|
# Add django_cfg API URLs
|
45
|
-
# Note:
|
46
|
-
# at /cfg/openapi/{group}/schema/ to avoid conflicts
|
41
|
+
# Note: URL prefixes (cfg/, health/, etc.) are defined in django_cfg.apps.urls
|
47
42
|
new_patterns = urlpatterns + [
|
48
|
-
path(
|
43
|
+
path("", include("django_cfg.apps.urls")),
|
49
44
|
]
|
50
45
|
|
51
46
|
# Add django-browser-reload URLs in development (if installed)
|
@@ -8,11 +8,11 @@ This replaces django-revolution with a cleaner, faster, type-safe implementation
|
|
8
8
|
"""
|
9
9
|
|
10
10
|
from typing import Dict, Any, Optional
|
11
|
-
from pydantic import
|
11
|
+
from pydantic import Field
|
12
12
|
from django_cfg.modules.django_client.core.config import OpenAPIConfig, OpenAPIGroupConfig
|
13
13
|
|
14
14
|
|
15
|
-
class
|
15
|
+
class OpenAPIClientConfig(OpenAPIConfig):
|
16
16
|
"""
|
17
17
|
Extended OpenAPI configuration with DRF parameters for django-cfg integration.
|
18
18
|
|
@@ -21,9 +21,9 @@ class ExtendedOpenAPIConfig(OpenAPIConfig):
|
|
21
21
|
|
22
22
|
Example:
|
23
23
|
```python
|
24
|
-
from django_cfg import
|
24
|
+
from django_cfg import OpenAPIClientConfig, OpenAPIGroupConfig
|
25
25
|
|
26
|
-
config =
|
26
|
+
config = OpenAPIClientConfig(
|
27
27
|
enabled=True,
|
28
28
|
groups=[
|
29
29
|
OpenAPIGroupConfig(
|
@@ -57,8 +57,8 @@ class ExtendedOpenAPIConfig(OpenAPIConfig):
|
|
57
57
|
description="Schema path prefix for DRF Spectacular"
|
58
58
|
)
|
59
59
|
drf_enable_browsable_api: bool = Field(
|
60
|
-
default=
|
61
|
-
description="Enable DRF browsable API"
|
60
|
+
default=True,
|
61
|
+
description="Enable DRF browsable API with Tailwind theme"
|
62
62
|
)
|
63
63
|
drf_enable_throttling: bool = Field(
|
64
64
|
default=False,
|
@@ -104,6 +104,8 @@ class ExtendedOpenAPIConfig(OpenAPIConfig):
|
|
104
104
|
def get_groups_with_defaults(self) -> Dict[str, OpenAPIGroupConfig]:
|
105
105
|
"""
|
106
106
|
Get groups with django-cfg default groups automatically added.
|
107
|
+
|
108
|
+
Automatically adds the 'cfg' group with all django-cfg apps if not explicitly defined.
|
107
109
|
|
108
110
|
Returns:
|
109
111
|
Dict of groups including default django-cfg groups
|
@@ -111,128 +113,13 @@ class ExtendedOpenAPIConfig(OpenAPIConfig):
|
|
111
113
|
# Convert list to dict for compatibility
|
112
114
|
groups_dict = {group.name: group for group in self.groups}
|
113
115
|
|
114
|
-
# Add default
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
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
|
116
|
+
# Add default 'cfg' group if not explicitly defined
|
117
|
+
if 'cfg' not in groups_dict:
|
118
|
+
try:
|
119
|
+
from django_cfg.apps.urls import get_default_cfg_group
|
120
|
+
groups_dict['cfg'] = get_default_cfg_group()
|
121
|
+
except Exception:
|
122
|
+
pass
|
233
123
|
|
234
124
|
return groups_dict
|
235
125
|
|
236
|
-
|
237
|
-
# Alias for easier import
|
238
|
-
OpenAPIClientConfig = ExtendedOpenAPIConfig
|
@@ -57,12 +57,12 @@ class ArchiveManager:
|
|
57
57
|
|
58
58
|
if python_dir and python_dir.exists():
|
59
59
|
dest = archive_path / "python"
|
60
|
-
shutil.copytree(python_dir, dest)
|
60
|
+
shutil.copytree(python_dir, dest, dirs_exist_ok=True)
|
61
61
|
copied["python"] = str(dest)
|
62
62
|
|
63
63
|
if typescript_dir and typescript_dir.exists():
|
64
64
|
dest = archive_path / "typescript"
|
65
|
-
shutil.copytree(typescript_dir, dest)
|
65
|
+
shutil.copytree(typescript_dir, dest, dirs_exist_ok=True)
|
66
66
|
copied["typescript"] = str(dest)
|
67
67
|
|
68
68
|
# Create metadata
|
@@ -76,6 +76,26 @@ class OpenAPIConfig(BaseModel):
|
|
76
76
|
description="Generate TypeScript client",
|
77
77
|
)
|
78
78
|
|
79
|
+
generate_package_files: bool = Field(
|
80
|
+
default=False,
|
81
|
+
description="Generate package.json (TypeScript) and pyproject.toml (Python)",
|
82
|
+
)
|
83
|
+
|
84
|
+
generate_zod_schemas: bool = Field(
|
85
|
+
default=False,
|
86
|
+
description="Generate Zod schemas for runtime validation (TypeScript only)",
|
87
|
+
)
|
88
|
+
|
89
|
+
generate_fetchers: bool = Field(
|
90
|
+
default=False,
|
91
|
+
description="Generate typed fetcher functions (TypeScript only, requires Zod schemas)",
|
92
|
+
)
|
93
|
+
|
94
|
+
generate_swr_hooks: bool = Field(
|
95
|
+
default=False,
|
96
|
+
description="Generate SWR hooks for React (TypeScript only, requires fetchers)",
|
97
|
+
)
|
98
|
+
|
79
99
|
client_structure: Literal["flat", "namespaced"] = Field(
|
80
100
|
default="namespaced",
|
81
101
|
description=(
|
@@ -59,7 +59,7 @@ class DjangoOpenAPI:
|
|
59
59
|
if not self.config:
|
60
60
|
return {}
|
61
61
|
|
62
|
-
# Use get_groups_with_defaults if available (
|
62
|
+
# Use get_groups_with_defaults if available (OpenAPIClientConfig)
|
63
63
|
if hasattr(self.config, 'get_groups_with_defaults'):
|
64
64
|
return self.config.get_groups_with_defaults()
|
65
65
|
|
@@ -22,10 +22,10 @@ Usage:
|
|
22
22
|
from pathlib import Path
|
23
23
|
from typing import Literal
|
24
24
|
|
25
|
-
from
|
26
|
-
from
|
27
|
-
from
|
28
|
-
from
|
25
|
+
from .base import GeneratedFile
|
26
|
+
from .python import PythonGenerator
|
27
|
+
from .typescript import TypeScriptGenerator
|
28
|
+
from ..ir import IRContext
|
29
29
|
|
30
30
|
__all__ = [
|
31
31
|
"PythonGenerator",
|
@@ -48,6 +48,11 @@ class BaseGenerator(ABC):
|
|
48
48
|
client_structure: str = "namespaced",
|
49
49
|
openapi_schema: dict | None = None,
|
50
50
|
tag_prefix: str = "",
|
51
|
+
package_config: dict | None = None,
|
52
|
+
generate_package_files: bool = False,
|
53
|
+
generate_zod_schemas: bool = False,
|
54
|
+
generate_fetchers: bool = False,
|
55
|
+
generate_swr_hooks: bool = False,
|
51
56
|
):
|
52
57
|
"""
|
53
58
|
Initialize generator with IR context.
|
@@ -57,11 +62,21 @@ class BaseGenerator(ABC):
|
|
57
62
|
client_structure: Client structure ("flat" or "namespaced")
|
58
63
|
openapi_schema: OpenAPI schema dict (for embedding in client)
|
59
64
|
tag_prefix: Prefix to add to all tag names (e.g., "cfg_")
|
65
|
+
package_config: Package configuration (name, version, author, etc.)
|
66
|
+
generate_package_files: Whether to generate package.json/pyproject.toml
|
67
|
+
generate_zod_schemas: Whether to generate Zod schemas (TypeScript only)
|
68
|
+
generate_fetchers: Whether to generate typed fetchers (TypeScript only)
|
69
|
+
generate_swr_hooks: Whether to generate SWR hooks (TypeScript only, React)
|
60
70
|
"""
|
61
71
|
self.context = context
|
62
72
|
self.client_structure = client_structure
|
63
73
|
self.openapi_schema = openapi_schema
|
64
74
|
self.tag_prefix = tag_prefix
|
75
|
+
self.package_config = package_config or {}
|
76
|
+
self.generate_package_files = generate_package_files
|
77
|
+
self.generate_zod_schemas = generate_zod_schemas
|
78
|
+
self.generate_fetchers = generate_fetchers
|
79
|
+
self.generate_swr_hooks = generate_swr_hooks
|
65
80
|
|
66
81
|
# ===== Namespaced Structure Helpers =====
|
67
82
|
|
@@ -765,3 +780,59 @@ class BaseGenerator(ABC):
|
|
765
780
|
lines.append(" ".join(current_line))
|
766
781
|
|
767
782
|
return lines
|
783
|
+
|
784
|
+
def format_enum_description(self, text: str) -> str:
|
785
|
+
"""
|
786
|
+
Format enum description by splitting bullet points.
|
787
|
+
|
788
|
+
Enum descriptions from OpenAPI often have the format:
|
789
|
+
"* `value1` - Desc1 * `value2` - Desc2"
|
790
|
+
|
791
|
+
This method splits them into separate lines:
|
792
|
+
"* `value1` - Desc1\n* `value2` - Desc2"
|
793
|
+
|
794
|
+
Args:
|
795
|
+
text: Enum description text
|
796
|
+
|
797
|
+
Returns:
|
798
|
+
Formatted description with proper line breaks
|
799
|
+
"""
|
800
|
+
if not text:
|
801
|
+
return text
|
802
|
+
|
803
|
+
# Split by " * `" pattern (preserving the first *)
|
804
|
+
import re
|
805
|
+
# Replace " * `" with newline + "* `"
|
806
|
+
formatted = re.sub(r'\s+\*\s+`', '\n* `', text.strip())
|
807
|
+
|
808
|
+
return formatted
|
809
|
+
|
810
|
+
def sanitize_enum_name(self, name: str) -> str:
|
811
|
+
"""
|
812
|
+
Sanitize enum name by converting to PascalCase.
|
813
|
+
|
814
|
+
Examples:
|
815
|
+
"OrderDetail.status" -> "OrderDetailStatus"
|
816
|
+
"Currency.currency_type" -> "CurrencyCurrencyType"
|
817
|
+
"CurrencyList.currency_type" -> "CurrencyListCurrencyType"
|
818
|
+
"User.role" -> "UserRole"
|
819
|
+
|
820
|
+
Args:
|
821
|
+
name: Original enum name (may contain dots, underscores)
|
822
|
+
|
823
|
+
Returns:
|
824
|
+
Sanitized PascalCase name
|
825
|
+
"""
|
826
|
+
# Replace dots with underscores, then split and convert to PascalCase
|
827
|
+
parts = name.replace('.', '_').split('_')
|
828
|
+
result = []
|
829
|
+
for word in parts:
|
830
|
+
if not word:
|
831
|
+
continue
|
832
|
+
# If word is already PascalCase/camelCase, keep it as is
|
833
|
+
# Otherwise capitalize first letter only
|
834
|
+
if word[0].isupper():
|
835
|
+
result.append(word)
|
836
|
+
else:
|
837
|
+
result.append(word[0].upper() + word[1:] if len(word) > 1 else word.upper())
|
838
|
+
return ''.join(result)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
"""
|
2
|
+
Python Generator - Generates Python client (Pydantic 2 + httpx).
|
3
|
+
|
4
|
+
This generator creates a complete Python API client from IR:
|
5
|
+
- Pydantic 2 models (Request/Response/Patch splits)
|
6
|
+
- Enum classes from x-enum-varnames
|
7
|
+
- httpx.AsyncClient for async HTTP
|
8
|
+
- Django CSRF/session handling
|
9
|
+
- Type-safe (MyPy strict mode compatible)
|
10
|
+
|
11
|
+
Reference: https://docs.pydantic.dev/latest/
|
12
|
+
"""
|
13
|
+
|
14
|
+
from .generator import PythonGenerator
|
15
|
+
|
16
|
+
__all__ = ['PythonGenerator']
|