django-cfg 1.4.10__py3-none-any.whl → 1.4.13__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 +73 -49
- django_cfg/core/integration/display/startup.py +30 -22
- django_cfg/core/integration/url_integration.py +15 -16
- 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 +162 -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 +208 -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 +838 -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/python/templates/__init__.py.jinja +9 -0
- django_cfg/modules/django_client/core/generator/python/templates/api_wrapper.py.jinja +153 -0
- django_cfg/modules/django_client/core/generator/python/templates/app_init.py.jinja +6 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/app_client.py.jinja +18 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/flat_client.py.jinja +38 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/main_client.py.jinja +68 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/main_client_file.py.jinja +14 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/operation_method.py.jinja +9 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/sub_client.py.jinja +18 -0
- 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/python/templates/client_file.py.jinja +13 -0
- django_cfg/modules/django_client/core/generator/python/templates/main_init.py.jinja +52 -0
- django_cfg/modules/django_client/core/generator/python/templates/models/app_models.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/python/templates/models/enum_class.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/python/templates/models/enums.py.jinja +8 -0
- django_cfg/modules/django_client/core/generator/python/templates/models/models.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/python/templates/models/schema_class.py.jinja +21 -0
- django_cfg/modules/django_client/core/generator/python/templates/pyproject.toml.jinja +55 -0
- django_cfg/modules/django_client/core/generator/python/templates/utils/logger.py.jinja +255 -0
- django_cfg/modules/django_client/core/generator/python/templates/utils/retry.py.jinja +271 -0
- django_cfg/modules/django_client/core/generator/python/templates/utils/schema.py.jinja +12 -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 +536 -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/typescript/templates/app_index.ts.jinja +2 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/app_client.ts.jinja +18 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/client.ts.jinja +403 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/flat_client.ts.jinja +109 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/main_client_file.ts.jinja +10 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/operation.ts.jinja +61 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/sub_client.ts.jinja +15 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client_file.ts.jinja +9 -0
- 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/typescript/templates/index.ts.jinja +5 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/main_index.ts.jinja +268 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/models/app_models.ts.jinja +8 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/models/enums.ts.jinja +4 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/models/models.ts.jinja +8 -0
- 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/typescript/templates/utils/errors.ts.jinja +116 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/http.ts.jinja +98 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/logger.ts.jinja +259 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/retry.ts.jinja +175 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/schema.ts.jinja +7 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/storage.ts.jinja +158 -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 +427 -0
- django_cfg/modules/django_client/management/commands/validate_openapi.py +343 -0
- django_cfg/modules/django_client/pytest.ini +30 -0
- django_cfg/modules/django_client/spectacular/__init__.py +10 -0
- django_cfg/modules/django_client/spectacular/async_detection.py +187 -0
- django_cfg/modules/django_client/spectacular/enum_naming.py +192 -0
- django_cfg/modules/django_client/urls.py +72 -0
- django_cfg/{dashboard → modules/django_dashboard}/DEBUG_README.md +2 -2
- django_cfg/{dashboard → modules/django_dashboard}/REFACTORING_SUMMARY.md +1 -1
- django_cfg/modules/django_dashboard/management/__init__.py +0 -0
- django_cfg/modules/django_dashboard/management/commands/__init__.py +0 -0
- django_cfg/{dashboard → modules/django_dashboard}/management/commands/debug_dashboard.py +5 -5
- django_cfg/modules/django_dashboard/sections/documentation.py +391 -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/LOGGING_GUIDE.md +1 -1
- 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 +21 -10
- 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.13.dist-info}/METADATA +2 -2
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/RECORD +224 -74
- django_cfg/management/commands/generate.py +0 -107
- /django_cfg/models/django/{revolution.py → revolution_legacy.py} +0 -0
- /django_cfg/{dashboard → modules/django_admin}/management/__init__.py +0 -0
- /django_cfg/{dashboard → modules/django_admin}/management/commands/__init__.py +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}/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/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.10.dist-info → django_cfg-1.4.13.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,329 @@
|
|
1
|
+
"""
|
2
|
+
Zod Schemas Generator - Generates Zod validation schemas from IR.
|
3
|
+
|
4
|
+
This generator creates Zod schemas for runtime validation:
|
5
|
+
- Object schemas (z.object)
|
6
|
+
- Enum schemas (z.nativeEnum)
|
7
|
+
- Array schemas (z.array)
|
8
|
+
- Type inference (z.infer<typeof Schema>)
|
9
|
+
"""
|
10
|
+
|
11
|
+
from __future__ import annotations
|
12
|
+
|
13
|
+
from jinja2 import Environment
|
14
|
+
from ..base import GeneratedFile, BaseGenerator
|
15
|
+
from ...ir import IRContext, IRSchemaObject
|
16
|
+
|
17
|
+
|
18
|
+
class SchemasGenerator:
|
19
|
+
"""
|
20
|
+
Generate Zod schemas from IR schemas.
|
21
|
+
|
22
|
+
Features:
|
23
|
+
- Runtime validation with Zod
|
24
|
+
- Type inference from schemas
|
25
|
+
- Enum validation with z.nativeEnum()
|
26
|
+
- Nested object validation
|
27
|
+
- Array and nullable types
|
28
|
+
"""
|
29
|
+
|
30
|
+
def __init__(self, jinja_env: Environment, context: IRContext, base: BaseGenerator):
|
31
|
+
self.jinja_env = jinja_env
|
32
|
+
self.context = context
|
33
|
+
self.base = base
|
34
|
+
|
35
|
+
def generate_schema(self, schema: IRSchemaObject) -> str:
|
36
|
+
"""
|
37
|
+
Generate Zod schema for a single IR schema.
|
38
|
+
|
39
|
+
Args:
|
40
|
+
schema: IRSchemaObject to convert to Zod
|
41
|
+
|
42
|
+
Returns:
|
43
|
+
Zod schema code as string
|
44
|
+
|
45
|
+
Examples:
|
46
|
+
>>> generate_schema(User)
|
47
|
+
export const UserSchema = z.object({
|
48
|
+
id: z.number(),
|
49
|
+
email: z.string().email(),
|
50
|
+
username: z.string().min(1).max(150),
|
51
|
+
})
|
52
|
+
"""
|
53
|
+
if schema.type == "object":
|
54
|
+
return self._generate_object_schema(schema)
|
55
|
+
elif schema.type == "array":
|
56
|
+
return self._generate_array_schema(schema)
|
57
|
+
elif schema.enum:
|
58
|
+
return self._generate_enum_schema(schema)
|
59
|
+
else:
|
60
|
+
# Primitive type
|
61
|
+
return self._map_type_to_zod(schema)
|
62
|
+
|
63
|
+
def _generate_object_schema(self, schema: IRSchemaObject) -> str:
|
64
|
+
"""Generate z.object() schema."""
|
65
|
+
lines = []
|
66
|
+
|
67
|
+
# Schema comment
|
68
|
+
if schema.description:
|
69
|
+
lines.append(f"/**\n * {schema.description}\n */")
|
70
|
+
|
71
|
+
# Start schema definition
|
72
|
+
lines.append(f"export const {schema.name}Schema = z.object({{")
|
73
|
+
|
74
|
+
# Generate fields
|
75
|
+
if schema.properties:
|
76
|
+
for prop_name, prop_schema in schema.properties.items():
|
77
|
+
field_code = self._generate_field(prop_name, prop_schema, schema.required)
|
78
|
+
lines.append(f" {field_code},")
|
79
|
+
|
80
|
+
lines.append("})")
|
81
|
+
|
82
|
+
return "\n".join(lines)
|
83
|
+
|
84
|
+
def _generate_field(
|
85
|
+
self,
|
86
|
+
name: str,
|
87
|
+
schema: IRSchemaObject,
|
88
|
+
required_fields: list[str],
|
89
|
+
) -> str:
|
90
|
+
"""
|
91
|
+
Generate Zod field validation.
|
92
|
+
|
93
|
+
Examples:
|
94
|
+
id: z.number()
|
95
|
+
email: z.string().email()
|
96
|
+
username: z.string().min(1).max(150)
|
97
|
+
status: z.nativeEnum(Enums.StatusEnum)
|
98
|
+
created_at: z.string().datetime()
|
99
|
+
"""
|
100
|
+
# Check if this field is an enum
|
101
|
+
if schema.enum and schema.name:
|
102
|
+
# Use enum validation
|
103
|
+
zod_type = f"z.nativeEnum(Enums.{self.base.sanitize_enum_name(schema.name)})"
|
104
|
+
# Check if this field is a reference to an enum
|
105
|
+
elif schema.ref and schema.ref in self.context.schemas:
|
106
|
+
ref_schema = self.context.schemas[schema.ref]
|
107
|
+
if ref_schema.enum:
|
108
|
+
# Reference to enum component
|
109
|
+
zod_type = f"z.nativeEnum(Enums.{self.base.sanitize_enum_name(schema.ref)})"
|
110
|
+
else:
|
111
|
+
# Reference to another schema
|
112
|
+
zod_type = f"{schema.ref}Schema"
|
113
|
+
else:
|
114
|
+
# Map TypeScript type to Zod type
|
115
|
+
zod_type = self._map_type_to_zod(schema)
|
116
|
+
|
117
|
+
# Check if required
|
118
|
+
is_required = name in required_fields
|
119
|
+
|
120
|
+
# Handle optional fields
|
121
|
+
if not is_required:
|
122
|
+
zod_type = f"{zod_type}.optional()"
|
123
|
+
|
124
|
+
# Handle nullable fields
|
125
|
+
if schema.nullable:
|
126
|
+
zod_type = f"{zod_type}.nullable()"
|
127
|
+
|
128
|
+
return f"{name}: {zod_type}"
|
129
|
+
|
130
|
+
def _map_type_to_zod(self, schema: IRSchemaObject) -> str:
|
131
|
+
"""
|
132
|
+
Map OpenAPI/TypeScript type to Zod validation.
|
133
|
+
|
134
|
+
Args:
|
135
|
+
schema: IRSchemaObject with type information
|
136
|
+
|
137
|
+
Returns:
|
138
|
+
Zod validation code
|
139
|
+
|
140
|
+
Examples:
|
141
|
+
string -> z.string()
|
142
|
+
string (format: email) -> z.string().email()
|
143
|
+
string (format: date-time) -> z.string().datetime()
|
144
|
+
string (format: uri) -> z.string().url()
|
145
|
+
integer -> z.number().int()
|
146
|
+
number -> z.number()
|
147
|
+
boolean -> z.boolean()
|
148
|
+
array -> z.array(...)
|
149
|
+
"""
|
150
|
+
schema_type = schema.type
|
151
|
+
schema_format = schema.format
|
152
|
+
|
153
|
+
# String types with format validation
|
154
|
+
if schema_type == "string":
|
155
|
+
base_type = "z.string()"
|
156
|
+
|
157
|
+
# Add format validation
|
158
|
+
if schema_format == "email":
|
159
|
+
base_type = "z.string().email()"
|
160
|
+
elif schema_format in ("date-time", "datetime"):
|
161
|
+
base_type = "z.string().datetime()"
|
162
|
+
elif schema_format == "date":
|
163
|
+
base_type = "z.string().date()"
|
164
|
+
elif schema_format in ("uri", "url"):
|
165
|
+
base_type = "z.string().url()"
|
166
|
+
elif schema_format == "uuid":
|
167
|
+
base_type = "z.string().uuid()"
|
168
|
+
|
169
|
+
# Add length constraints
|
170
|
+
if schema.min_length is not None:
|
171
|
+
base_type = f"{base_type}.min({schema.min_length})"
|
172
|
+
if schema.max_length is not None:
|
173
|
+
base_type = f"{base_type}.max({schema.max_length})"
|
174
|
+
|
175
|
+
# Add pattern validation
|
176
|
+
if schema.pattern:
|
177
|
+
# Escape regex pattern for JS
|
178
|
+
escaped_pattern = schema.pattern.replace('\\', '\\\\')
|
179
|
+
base_type = f"{base_type}.regex(/{escaped_pattern}/)"
|
180
|
+
|
181
|
+
return base_type
|
182
|
+
|
183
|
+
# Integer type
|
184
|
+
elif schema_type == "integer":
|
185
|
+
base_type = "z.number().int()"
|
186
|
+
|
187
|
+
# Add range constraints
|
188
|
+
if schema.minimum is not None:
|
189
|
+
base_type = f"{base_type}.min({schema.minimum})"
|
190
|
+
if schema.maximum is not None:
|
191
|
+
base_type = f"{base_type}.max({schema.maximum})"
|
192
|
+
|
193
|
+
return base_type
|
194
|
+
|
195
|
+
# Number type
|
196
|
+
elif schema_type == "number":
|
197
|
+
base_type = "z.number()"
|
198
|
+
|
199
|
+
# Add range constraints
|
200
|
+
if schema.minimum is not None:
|
201
|
+
base_type = f"{base_type}.min({schema.minimum})"
|
202
|
+
if schema.maximum is not None:
|
203
|
+
base_type = f"{base_type}.max({schema.maximum})"
|
204
|
+
|
205
|
+
return base_type
|
206
|
+
|
207
|
+
# Boolean type
|
208
|
+
elif schema_type == "boolean":
|
209
|
+
return "z.boolean()"
|
210
|
+
|
211
|
+
# Array type
|
212
|
+
elif schema_type == "array":
|
213
|
+
if schema.items:
|
214
|
+
item_type = self._map_type_to_zod(schema.items)
|
215
|
+
return f"z.array({item_type})"
|
216
|
+
return "z.array(z.any())"
|
217
|
+
|
218
|
+
# Object type
|
219
|
+
elif schema_type == "object":
|
220
|
+
# Only reference schema if it's a defined component (not an inline property)
|
221
|
+
# Inline objects should use z.record() or z.object({})
|
222
|
+
if schema.ref:
|
223
|
+
# Explicit reference
|
224
|
+
return f"{schema.ref}Schema"
|
225
|
+
elif schema.properties:
|
226
|
+
# Inline object with properties - shouldn't reach here, but use z.object
|
227
|
+
return "z.object({})"
|
228
|
+
else:
|
229
|
+
# Object with no properties (like additionalProperties: {})
|
230
|
+
# Use z.record(z.string(), z.any()) for dynamic objects
|
231
|
+
return "z.record(z.string(), z.any())"
|
232
|
+
|
233
|
+
# Fallback to any
|
234
|
+
return "z.any()"
|
235
|
+
|
236
|
+
def _generate_array_schema(self, schema: IRSchemaObject) -> str:
|
237
|
+
"""Generate z.array() schema."""
|
238
|
+
lines = []
|
239
|
+
|
240
|
+
if schema.description:
|
241
|
+
lines.append(f"/**\n * {schema.description}\n */")
|
242
|
+
|
243
|
+
item_type = "z.any()"
|
244
|
+
if schema.items:
|
245
|
+
item_type = self._map_type_to_zod(schema.items)
|
246
|
+
|
247
|
+
lines.append(f"export const {schema.name}Schema = z.array({item_type})")
|
248
|
+
|
249
|
+
return "\n".join(lines)
|
250
|
+
|
251
|
+
def _generate_enum_schema(self, schema: IRSchemaObject) -> str:
|
252
|
+
"""Generate z.nativeEnum() schema."""
|
253
|
+
enum_name = self.base.sanitize_enum_name(schema.name)
|
254
|
+
|
255
|
+
lines = []
|
256
|
+
|
257
|
+
if schema.description:
|
258
|
+
lines.append(f"/**\n * {schema.description}\n */")
|
259
|
+
|
260
|
+
lines.append(f"export const {enum_name}Schema = z.nativeEnum(Enums.{enum_name})")
|
261
|
+
|
262
|
+
return "\n".join(lines)
|
263
|
+
|
264
|
+
def generate_schema_file(self, schema: IRSchemaObject, refs: set[str]) -> GeneratedFile:
|
265
|
+
"""
|
266
|
+
Generate individual Zod schema file.
|
267
|
+
|
268
|
+
Args:
|
269
|
+
schema: Schema to generate
|
270
|
+
refs: Set of schema names that are referenced
|
271
|
+
|
272
|
+
Returns:
|
273
|
+
GeneratedFile with Zod schema
|
274
|
+
"""
|
275
|
+
# Generate schema code
|
276
|
+
schema_code = self.generate_schema(schema)
|
277
|
+
|
278
|
+
# Check if has enums
|
279
|
+
has_enums = self._schema_uses_enums(schema)
|
280
|
+
|
281
|
+
# Render template
|
282
|
+
template = self.jinja_env.get_template("schemas/schema.ts.jinja")
|
283
|
+
content = template.render(
|
284
|
+
schema_name=schema.name,
|
285
|
+
description=schema.description,
|
286
|
+
schema_code=schema_code,
|
287
|
+
has_enums=has_enums,
|
288
|
+
has_refs=bool(refs),
|
289
|
+
refs=sorted(refs),
|
290
|
+
)
|
291
|
+
|
292
|
+
return GeneratedFile(
|
293
|
+
path=f"_utils/schemas/{schema.name}.schema.ts",
|
294
|
+
content=content,
|
295
|
+
description=f"Zod schema for {schema.name}",
|
296
|
+
)
|
297
|
+
|
298
|
+
def generate_schemas_index_file(self, schema_names: list[str]) -> GeneratedFile:
|
299
|
+
"""Generate index.ts for schemas folder."""
|
300
|
+
template = self.jinja_env.get_template("schemas/index.ts.jinja")
|
301
|
+
content = template.render(schema_names=sorted(schema_names))
|
302
|
+
|
303
|
+
return GeneratedFile(
|
304
|
+
path="_utils/schemas/index.ts",
|
305
|
+
content=content,
|
306
|
+
description="Zod schemas index",
|
307
|
+
)
|
308
|
+
|
309
|
+
def _schema_uses_enums(self, schema: IRSchemaObject) -> bool:
|
310
|
+
"""Check if schema uses any enums."""
|
311
|
+
if schema.enum:
|
312
|
+
return True
|
313
|
+
|
314
|
+
if schema.properties:
|
315
|
+
for prop in schema.properties.values():
|
316
|
+
if prop.enum or (prop.ref and self._is_enum_ref(prop.ref)):
|
317
|
+
return True
|
318
|
+
|
319
|
+
if schema.items:
|
320
|
+
if schema.items.enum or (schema.items.ref and self._is_enum_ref(schema.items.ref)):
|
321
|
+
return True
|
322
|
+
|
323
|
+
return False
|
324
|
+
|
325
|
+
def _is_enum_ref(self, ref: str) -> bool:
|
326
|
+
"""Check if reference points to an enum."""
|
327
|
+
if ref in self.context.schemas:
|
328
|
+
return self.context.schemas[ref].enum is not None
|
329
|
+
return False
|
@@ -0,0 +1,131 @@
|
|
1
|
+
/**
|
2
|
+
* Global API Instance - Singleton configuration
|
3
|
+
*
|
4
|
+
* This module provides a global API instance that can be configured once
|
5
|
+
* and used throughout your application.
|
6
|
+
*
|
7
|
+
* Usage:
|
8
|
+
* ```typescript
|
9
|
+
* // Configure once (e.g., in your app entry point)
|
10
|
+
* import { configureAPI } from './api-instance'
|
11
|
+
*
|
12
|
+
* configureAPI({
|
13
|
+
* baseUrl: 'https://api.example.com',
|
14
|
+
* token: 'your-jwt-token'
|
15
|
+
* })
|
16
|
+
*
|
17
|
+
* // Then use fetchers and hooks anywhere without configuration
|
18
|
+
* import { getUsers } from './fetchers'
|
19
|
+
* const users = await getUsers({ page: 1 })
|
20
|
+
* ```
|
21
|
+
*
|
22
|
+
* For SSR or multiple instances:
|
23
|
+
* ```typescript
|
24
|
+
* import { API } from './index'
|
25
|
+
* import { getUsers } from './fetchers'
|
26
|
+
*
|
27
|
+
* const api = new API('https://api.example.com')
|
28
|
+
* const users = await getUsers({ page: 1 }, api)
|
29
|
+
* ```
|
30
|
+
*/
|
31
|
+
|
32
|
+
import { API, type APIOptions } from './index'
|
33
|
+
|
34
|
+
let globalAPI: API | null = null
|
35
|
+
|
36
|
+
/**
|
37
|
+
* Get the global API instance
|
38
|
+
* @throws Error if API is not configured
|
39
|
+
*/
|
40
|
+
export function getAPIInstance(): API {
|
41
|
+
if (!globalAPI) {
|
42
|
+
throw new Error(
|
43
|
+
'API not configured. Call configureAPI() with your base URL before using fetchers or hooks.\n\n' +
|
44
|
+
'Example:\n' +
|
45
|
+
' import { configureAPI } from "./api-instance"\n' +
|
46
|
+
' configureAPI({ baseUrl: "https://api.example.com" })'
|
47
|
+
)
|
48
|
+
}
|
49
|
+
return globalAPI
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
* Check if API is configured
|
54
|
+
*/
|
55
|
+
export function isAPIConfigured(): boolean {
|
56
|
+
return globalAPI !== null
|
57
|
+
}
|
58
|
+
|
59
|
+
/**
|
60
|
+
* Configure the global API instance
|
61
|
+
*
|
62
|
+
* @param baseUrl - Base URL for the API
|
63
|
+
* @param options - Optional configuration (storage, retry, logger)
|
64
|
+
*
|
65
|
+
* @example
|
66
|
+
* ```typescript
|
67
|
+
* configureAPI({
|
68
|
+
* baseUrl: 'https://api.example.com',
|
69
|
+
* token: 'jwt-token',
|
70
|
+
* options: {
|
71
|
+
* retryConfig: { maxRetries: 3 },
|
72
|
+
* loggerConfig: { enabled: true }
|
73
|
+
* }
|
74
|
+
* })
|
75
|
+
* ```
|
76
|
+
*/
|
77
|
+
export function configureAPI(config: {
|
78
|
+
baseUrl: string
|
79
|
+
token?: string
|
80
|
+
refreshToken?: string
|
81
|
+
options?: APIOptions
|
82
|
+
}): API {
|
83
|
+
globalAPI = new API(config.baseUrl, config.options)
|
84
|
+
|
85
|
+
if (config.token) {
|
86
|
+
globalAPI.setToken(config.token, config.refreshToken)
|
87
|
+
}
|
88
|
+
|
89
|
+
return globalAPI
|
90
|
+
}
|
91
|
+
|
92
|
+
/**
|
93
|
+
* Reconfigure the global API instance with new settings
|
94
|
+
* Useful for updating tokens or base URL
|
95
|
+
*/
|
96
|
+
export function reconfigureAPI(updates: {
|
97
|
+
baseUrl?: string
|
98
|
+
token?: string
|
99
|
+
refreshToken?: string
|
100
|
+
}): API {
|
101
|
+
const instance = getAPIInstance()
|
102
|
+
|
103
|
+
if (updates.baseUrl) {
|
104
|
+
instance.setBaseUrl(updates.baseUrl)
|
105
|
+
}
|
106
|
+
|
107
|
+
if (updates.token) {
|
108
|
+
instance.setToken(updates.token, updates.refreshToken)
|
109
|
+
}
|
110
|
+
|
111
|
+
return instance
|
112
|
+
}
|
113
|
+
|
114
|
+
/**
|
115
|
+
* Clear tokens from the global API instance
|
116
|
+
*/
|
117
|
+
export function clearAPITokens(): void {
|
118
|
+
const instance = getAPIInstance()
|
119
|
+
instance.clearTokens()
|
120
|
+
}
|
121
|
+
|
122
|
+
/**
|
123
|
+
* Reset the global API instance
|
124
|
+
* Useful for testing or logout scenarios
|
125
|
+
*/
|
126
|
+
export function resetAPI(): void {
|
127
|
+
if (globalAPI) {
|
128
|
+
globalAPI.clearTokens()
|
129
|
+
}
|
130
|
+
globalAPI = null
|
131
|
+
}
|
django_cfg/modules/django_client/core/generator/typescript/templates/client/app_client.ts.jinja
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
import * as Models from "./models";
|
2
|
+
|
3
|
+
|
4
|
+
/**
|
5
|
+
* API endpoints for {{ tag }}.
|
6
|
+
*/
|
7
|
+
export class {{ class_name }} {
|
8
|
+
private client: any;
|
9
|
+
|
10
|
+
constructor(client: any) {
|
11
|
+
this.client = client;
|
12
|
+
}
|
13
|
+
|
14
|
+
{% for operation in operations %}
|
15
|
+
{{ operation }}
|
16
|
+
|
17
|
+
{% endfor %}
|
18
|
+
}
|