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.
Files changed (225) hide show
  1. django_cfg/apps/agents/management/commands/create_agent.py +1 -1
  2. django_cfg/apps/agents/management/commands/orchestrator_status.py +3 -3
  3. django_cfg/apps/newsletter/serializers.py +40 -3
  4. django_cfg/apps/newsletter/views/campaigns.py +12 -3
  5. django_cfg/apps/newsletter/views/emails.py +14 -3
  6. django_cfg/apps/newsletter/views/subscriptions.py +12 -2
  7. django_cfg/apps/payments/views/api/currencies.py +49 -6
  8. django_cfg/apps/payments/views/api/webhooks.py +72 -7
  9. django_cfg/apps/payments/views/overview/serializers.py +34 -1
  10. django_cfg/apps/payments/views/overview/views.py +2 -1
  11. django_cfg/apps/payments/views/serializers/payments.py +6 -6
  12. django_cfg/apps/urls.py +106 -45
  13. django_cfg/core/base/config_model.py +2 -2
  14. django_cfg/core/constants.py +1 -1
  15. django_cfg/core/generation/integration_generators/__init__.py +1 -1
  16. django_cfg/core/generation/integration_generators/api.py +73 -49
  17. django_cfg/core/integration/display/startup.py +30 -22
  18. django_cfg/core/integration/url_integration.py +15 -16
  19. django_cfg/management/commands/check_endpoints.py +11 -160
  20. django_cfg/management/commands/check_settings.py +13 -348
  21. django_cfg/management/commands/clear_constance.py +13 -201
  22. django_cfg/management/commands/create_token.py +13 -321
  23. django_cfg/management/commands/generate_clients.py +23 -0
  24. django_cfg/management/commands/list_urls.py +13 -306
  25. django_cfg/management/commands/migrate_all.py +13 -126
  26. django_cfg/management/commands/migrator.py +13 -396
  27. django_cfg/management/commands/rundramatiq.py +15 -247
  28. django_cfg/management/commands/rundramatiq_simulator.py +12 -429
  29. django_cfg/management/commands/runserver_ngrok.py +15 -160
  30. django_cfg/management/commands/script.py +12 -488
  31. django_cfg/management/commands/show_config.py +12 -215
  32. django_cfg/management/commands/show_urls.py +12 -342
  33. django_cfg/management/commands/superuser.py +15 -295
  34. django_cfg/management/commands/task_clear.py +14 -217
  35. django_cfg/management/commands/task_status.py +13 -248
  36. django_cfg/management/commands/test_email.py +15 -86
  37. django_cfg/management/commands/test_telegram.py +14 -61
  38. django_cfg/management/commands/test_twilio.py +15 -105
  39. django_cfg/management/commands/tree.py +13 -383
  40. django_cfg/management/commands/validate_openapi.py +10 -0
  41. django_cfg/middleware/README.md +1 -1
  42. django_cfg/middleware/user_activity.py +3 -3
  43. django_cfg/models/__init__.py +2 -2
  44. django_cfg/models/api/drf/spectacular.py +6 -6
  45. django_cfg/models/django/__init__.py +2 -2
  46. django_cfg/models/django/openapi.py +162 -0
  47. django_cfg/modules/django_admin/management/commands/check_endpoints.py +169 -0
  48. django_cfg/modules/django_admin/management/commands/check_settings.py +355 -0
  49. django_cfg/modules/django_admin/management/commands/clear_constance.py +208 -0
  50. django_cfg/modules/django_admin/management/commands/create_token.py +328 -0
  51. django_cfg/modules/django_admin/management/commands/list_urls.py +313 -0
  52. django_cfg/modules/django_admin/management/commands/migrate_all.py +133 -0
  53. django_cfg/modules/django_admin/management/commands/migrator.py +403 -0
  54. django_cfg/modules/django_admin/management/commands/script.py +496 -0
  55. django_cfg/modules/django_admin/management/commands/show_config.py +225 -0
  56. django_cfg/modules/django_admin/management/commands/show_urls.py +361 -0
  57. django_cfg/modules/django_admin/management/commands/superuser.py +302 -0
  58. django_cfg/modules/django_admin/management/commands/tree.py +390 -0
  59. django_cfg/modules/django_client/__init__.py +20 -0
  60. django_cfg/modules/django_client/apps.py +35 -0
  61. django_cfg/modules/django_client/core/__init__.py +56 -0
  62. django_cfg/modules/django_client/core/archive/__init__.py +11 -0
  63. django_cfg/modules/django_client/core/archive/manager.py +134 -0
  64. django_cfg/modules/django_client/core/cli/__init__.py +12 -0
  65. django_cfg/modules/django_client/core/cli/main.py +235 -0
  66. django_cfg/modules/django_client/core/config/__init__.py +18 -0
  67. django_cfg/modules/django_client/core/config/config.py +208 -0
  68. django_cfg/modules/django_client/core/config/group.py +101 -0
  69. django_cfg/modules/django_client/core/config/service.py +209 -0
  70. django_cfg/modules/django_client/core/generator/__init__.py +115 -0
  71. django_cfg/modules/django_client/core/generator/base.py +838 -0
  72. django_cfg/modules/django_client/core/generator/python/__init__.py +16 -0
  73. django_cfg/modules/django_client/core/generator/python/async_client_gen.py +174 -0
  74. django_cfg/modules/django_client/core/generator/python/files_generator.py +180 -0
  75. django_cfg/modules/django_client/core/generator/python/generator.py +182 -0
  76. django_cfg/modules/django_client/core/generator/python/models_generator.py +318 -0
  77. django_cfg/modules/django_client/core/generator/python/operations_generator.py +278 -0
  78. django_cfg/modules/django_client/core/generator/python/sync_client_gen.py +102 -0
  79. django_cfg/modules/django_client/core/generator/python/templates/__init__.py.jinja +9 -0
  80. django_cfg/modules/django_client/core/generator/python/templates/api_wrapper.py.jinja +153 -0
  81. django_cfg/modules/django_client/core/generator/python/templates/app_init.py.jinja +6 -0
  82. django_cfg/modules/django_client/core/generator/python/templates/client/app_client.py.jinja +18 -0
  83. django_cfg/modules/django_client/core/generator/python/templates/client/flat_client.py.jinja +38 -0
  84. django_cfg/modules/django_client/core/generator/python/templates/client/main_client.py.jinja +68 -0
  85. django_cfg/modules/django_client/core/generator/python/templates/client/main_client_file.py.jinja +14 -0
  86. django_cfg/modules/django_client/core/generator/python/templates/client/operation_method.py.jinja +9 -0
  87. django_cfg/modules/django_client/core/generator/python/templates/client/sub_client.py.jinja +18 -0
  88. django_cfg/modules/django_client/core/generator/python/templates/client/sync_main_client.py.jinja +50 -0
  89. django_cfg/modules/django_client/core/generator/python/templates/client/sync_operation_method.py.jinja +9 -0
  90. django_cfg/modules/django_client/core/generator/python/templates/client/sync_sub_client.py.jinja +18 -0
  91. django_cfg/modules/django_client/core/generator/python/templates/client_file.py.jinja +13 -0
  92. django_cfg/modules/django_client/core/generator/python/templates/main_init.py.jinja +52 -0
  93. django_cfg/modules/django_client/core/generator/python/templates/models/app_models.py.jinja +17 -0
  94. django_cfg/modules/django_client/core/generator/python/templates/models/enum_class.py.jinja +17 -0
  95. django_cfg/modules/django_client/core/generator/python/templates/models/enums.py.jinja +8 -0
  96. django_cfg/modules/django_client/core/generator/python/templates/models/models.py.jinja +17 -0
  97. django_cfg/modules/django_client/core/generator/python/templates/models/schema_class.py.jinja +21 -0
  98. django_cfg/modules/django_client/core/generator/python/templates/pyproject.toml.jinja +55 -0
  99. django_cfg/modules/django_client/core/generator/python/templates/utils/logger.py.jinja +255 -0
  100. django_cfg/modules/django_client/core/generator/python/templates/utils/retry.py.jinja +271 -0
  101. django_cfg/modules/django_client/core/generator/python/templates/utils/schema.py.jinja +12 -0
  102. django_cfg/modules/django_client/core/generator/typescript/__init__.py +14 -0
  103. django_cfg/modules/django_client/core/generator/typescript/client_generator.py +165 -0
  104. django_cfg/modules/django_client/core/generator/typescript/fetchers_generator.py +428 -0
  105. django_cfg/modules/django_client/core/generator/typescript/files_generator.py +207 -0
  106. django_cfg/modules/django_client/core/generator/typescript/generator.py +432 -0
  107. django_cfg/modules/django_client/core/generator/typescript/hooks_generator.py +536 -0
  108. django_cfg/modules/django_client/core/generator/typescript/models_generator.py +245 -0
  109. django_cfg/modules/django_client/core/generator/typescript/operations_generator.py +298 -0
  110. django_cfg/modules/django_client/core/generator/typescript/schemas_generator.py +329 -0
  111. django_cfg/modules/django_client/core/generator/typescript/templates/api_instance.ts.jinja +131 -0
  112. django_cfg/modules/django_client/core/generator/typescript/templates/app_index.ts.jinja +2 -0
  113. django_cfg/modules/django_client/core/generator/typescript/templates/client/app_client.ts.jinja +18 -0
  114. django_cfg/modules/django_client/core/generator/typescript/templates/client/client.ts.jinja +403 -0
  115. django_cfg/modules/django_client/core/generator/typescript/templates/client/flat_client.ts.jinja +109 -0
  116. django_cfg/modules/django_client/core/generator/typescript/templates/client/main_client_file.ts.jinja +10 -0
  117. django_cfg/modules/django_client/core/generator/typescript/templates/client/operation.ts.jinja +61 -0
  118. django_cfg/modules/django_client/core/generator/typescript/templates/client/sub_client.ts.jinja +15 -0
  119. django_cfg/modules/django_client/core/generator/typescript/templates/client_file.ts.jinja +9 -0
  120. django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/fetchers.ts.jinja +45 -0
  121. django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/index.ts.jinja +30 -0
  122. django_cfg/modules/django_client/core/generator/typescript/templates/index.ts.jinja +5 -0
  123. django_cfg/modules/django_client/core/generator/typescript/templates/main_index.ts.jinja +268 -0
  124. django_cfg/modules/django_client/core/generator/typescript/templates/models/app_models.ts.jinja +8 -0
  125. django_cfg/modules/django_client/core/generator/typescript/templates/models/enums.ts.jinja +4 -0
  126. django_cfg/modules/django_client/core/generator/typescript/templates/models/models.ts.jinja +8 -0
  127. django_cfg/modules/django_client/core/generator/typescript/templates/package.json.jinja +52 -0
  128. django_cfg/modules/django_client/core/generator/typescript/templates/schemas/index.ts.jinja +21 -0
  129. django_cfg/modules/django_client/core/generator/typescript/templates/schemas/schema.ts.jinja +24 -0
  130. django_cfg/modules/django_client/core/generator/typescript/templates/tsconfig.json.jinja +20 -0
  131. django_cfg/modules/django_client/core/generator/typescript/templates/utils/errors.ts.jinja +116 -0
  132. django_cfg/modules/django_client/core/generator/typescript/templates/utils/http.ts.jinja +98 -0
  133. django_cfg/modules/django_client/core/generator/typescript/templates/utils/logger.ts.jinja +259 -0
  134. django_cfg/modules/django_client/core/generator/typescript/templates/utils/retry.ts.jinja +175 -0
  135. django_cfg/modules/django_client/core/generator/typescript/templates/utils/schema.ts.jinja +7 -0
  136. django_cfg/modules/django_client/core/generator/typescript/templates/utils/storage.ts.jinja +158 -0
  137. django_cfg/modules/django_client/core/groups/__init__.py +13 -0
  138. django_cfg/modules/django_client/core/groups/detector.py +178 -0
  139. django_cfg/modules/django_client/core/groups/manager.py +314 -0
  140. django_cfg/modules/django_client/core/ir/__init__.py +57 -0
  141. django_cfg/modules/django_client/core/ir/context.py +387 -0
  142. django_cfg/modules/django_client/core/ir/operation.py +518 -0
  143. django_cfg/modules/django_client/core/ir/schema.py +353 -0
  144. django_cfg/modules/django_client/core/parser/__init__.py +74 -0
  145. django_cfg/modules/django_client/core/parser/base.py +648 -0
  146. django_cfg/modules/django_client/core/parser/models/__init__.py +74 -0
  147. django_cfg/modules/django_client/core/parser/models/base.py +212 -0
  148. django_cfg/modules/django_client/core/parser/models/components.py +160 -0
  149. django_cfg/modules/django_client/core/parser/models/openapi.py +203 -0
  150. django_cfg/modules/django_client/core/parser/models/operation.py +207 -0
  151. django_cfg/modules/django_client/core/parser/models/schema.py +266 -0
  152. django_cfg/modules/django_client/core/parser/openapi30.py +56 -0
  153. django_cfg/modules/django_client/core/parser/openapi31.py +64 -0
  154. django_cfg/modules/django_client/core/validation/__init__.py +22 -0
  155. django_cfg/modules/django_client/core/validation/checker.py +134 -0
  156. django_cfg/modules/django_client/core/validation/fixer.py +216 -0
  157. django_cfg/modules/django_client/core/validation/reporter.py +480 -0
  158. django_cfg/modules/django_client/core/validation/rules/__init__.py +11 -0
  159. django_cfg/modules/django_client/core/validation/rules/base.py +96 -0
  160. django_cfg/modules/django_client/core/validation/rules/type_hints.py +288 -0
  161. django_cfg/modules/django_client/core/validation/safety.py +266 -0
  162. django_cfg/modules/django_client/management/__init__.py +3 -0
  163. django_cfg/modules/django_client/management/commands/__init__.py +3 -0
  164. django_cfg/modules/django_client/management/commands/generate_client.py +427 -0
  165. django_cfg/modules/django_client/management/commands/validate_openapi.py +343 -0
  166. django_cfg/modules/django_client/pytest.ini +30 -0
  167. django_cfg/modules/django_client/spectacular/__init__.py +10 -0
  168. django_cfg/modules/django_client/spectacular/async_detection.py +187 -0
  169. django_cfg/modules/django_client/spectacular/enum_naming.py +192 -0
  170. django_cfg/modules/django_client/urls.py +72 -0
  171. django_cfg/{dashboard → modules/django_dashboard}/DEBUG_README.md +2 -2
  172. django_cfg/{dashboard → modules/django_dashboard}/REFACTORING_SUMMARY.md +1 -1
  173. django_cfg/modules/django_dashboard/management/__init__.py +0 -0
  174. django_cfg/modules/django_dashboard/management/commands/__init__.py +0 -0
  175. django_cfg/{dashboard → modules/django_dashboard}/management/commands/debug_dashboard.py +5 -5
  176. django_cfg/modules/django_dashboard/sections/documentation.py +391 -0
  177. django_cfg/modules/django_email/management/__init__.py +0 -0
  178. django_cfg/modules/django_email/management/commands/__init__.py +0 -0
  179. django_cfg/modules/django_email/management/commands/test_email.py +93 -0
  180. django_cfg/modules/django_logging/LOGGING_GUIDE.md +1 -1
  181. django_cfg/modules/django_logging/django_logger.py +6 -6
  182. django_cfg/modules/django_ngrok/management/__init__.py +0 -0
  183. django_cfg/modules/django_ngrok/management/commands/__init__.py +0 -0
  184. django_cfg/modules/django_ngrok/management/commands/runserver_ngrok.py +167 -0
  185. django_cfg/modules/django_tasks/management/__init__.py +0 -0
  186. django_cfg/modules/django_tasks/management/commands/__init__.py +0 -0
  187. django_cfg/modules/django_tasks/management/commands/rundramatiq.py +254 -0
  188. django_cfg/modules/django_tasks/management/commands/rundramatiq_simulator.py +437 -0
  189. django_cfg/modules/django_tasks/management/commands/task_clear.py +226 -0
  190. django_cfg/modules/django_tasks/management/commands/task_status.py +257 -0
  191. django_cfg/modules/django_telegram/management/__init__.py +0 -0
  192. django_cfg/modules/django_telegram/management/commands/__init__.py +0 -0
  193. django_cfg/modules/django_telegram/management/commands/test_telegram.py +68 -0
  194. django_cfg/modules/django_twilio/management/__init__.py +0 -0
  195. django_cfg/modules/django_twilio/management/commands/__init__.py +0 -0
  196. django_cfg/modules/django_twilio/management/commands/test_twilio.py +112 -0
  197. django_cfg/modules/django_unfold/callbacks/main.py +21 -10
  198. django_cfg/modules/django_unfold/callbacks/revolution.py +41 -36
  199. django_cfg/pyproject.toml +2 -6
  200. django_cfg/registry/third_party.py +5 -7
  201. django_cfg/routing/callbacks.py +1 -1
  202. django_cfg/static/admin/css/prose-unfold.css +666 -0
  203. django_cfg/templates/admin/index.html +8 -0
  204. django_cfg/templates/admin/index_new.html +13 -0
  205. django_cfg/templates/admin/layouts/dashboard_with_tabs.html +15 -3
  206. django_cfg/templates/admin/sections/documentation_section.html +172 -0
  207. django_cfg/templates/admin/snippets/tabs/documentation_tab.html +231 -0
  208. {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/METADATA +2 -2
  209. {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/RECORD +224 -74
  210. django_cfg/management/commands/generate.py +0 -107
  211. /django_cfg/models/django/{revolution.py → revolution_legacy.py} +0 -0
  212. /django_cfg/{dashboard → modules/django_admin}/management/__init__.py +0 -0
  213. /django_cfg/{dashboard → modules/django_admin}/management/commands/__init__.py +0 -0
  214. /django_cfg/{dashboard → modules/django_dashboard}/__init__.py +0 -0
  215. /django_cfg/{dashboard → modules/django_dashboard}/components.py +0 -0
  216. /django_cfg/{dashboard → modules/django_dashboard}/debug.py +0 -0
  217. /django_cfg/{dashboard → modules/django_dashboard}/sections/__init__.py +0 -0
  218. /django_cfg/{dashboard → modules/django_dashboard}/sections/base.py +0 -0
  219. /django_cfg/{dashboard → modules/django_dashboard}/sections/commands.py +0 -0
  220. /django_cfg/{dashboard → modules/django_dashboard}/sections/overview.py +0 -0
  221. /django_cfg/{dashboard → modules/django_dashboard}/sections/stats.py +0 -0
  222. /django_cfg/{dashboard → modules/django_dashboard}/sections/system.py +0 -0
  223. {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/WHEEL +0 -0
  224. {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/entry_points.txt +0 -0
  225. {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
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./client";
2
+ export * as Models from "./models";
@@ -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
+ }