swiftpy-framework 0.1.0__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 (211) hide show
  1. swiftpy/.gitignore +0 -0
  2. swiftpy/__init__.py +572 -0
  3. swiftpy/admin/__init__.py +50 -0
  4. swiftpy/admin/auth.py +522 -0
  5. swiftpy/admin/registry.py +567 -0
  6. swiftpy/admin/views.py +1583 -0
  7. swiftpy/ai/__init__.py +199 -0
  8. swiftpy/ai/_deterministic.py +40 -0
  9. swiftpy/ai/_fake.py +604 -0
  10. swiftpy/ai/agents/__init__.py +30 -0
  11. swiftpy/ai/agents/base_agent.py +506 -0
  12. swiftpy/ai/agents/memory.py +864 -0
  13. swiftpy/ai/client.py +1011 -0
  14. swiftpy/ai/conversation.py +171 -0
  15. swiftpy/ai/embeddings.py +321 -0
  16. swiftpy/ai/exceptions.py +75 -0
  17. swiftpy/ai/history_strategies.py +157 -0
  18. swiftpy/ai/middleware.py +918 -0
  19. swiftpy/ai/observability/__init__.py +28 -0
  20. swiftpy/ai/observability/drivers.py +763 -0
  21. swiftpy/ai/observability/observer.py +364 -0
  22. swiftpy/ai/pool.py +102 -0
  23. swiftpy/ai/pricing.py +101 -0
  24. swiftpy/ai/prompts/__init__.py +6 -0
  25. swiftpy/ai/prompts/loader.py +343 -0
  26. swiftpy/ai/providers/__init__.py +22 -0
  27. swiftpy/ai/providers/anthropic_provider.py +353 -0
  28. swiftpy/ai/providers/base.py +273 -0
  29. swiftpy/ai/providers/openai_provider.py +275 -0
  30. swiftpy/ai/rag/__init__.py +53 -0
  31. swiftpy/ai/rag/context_formatter.py +263 -0
  32. swiftpy/ai/rag/pipeline_builder.py +544 -0
  33. swiftpy/ai/rag/reranker.py +484 -0
  34. swiftpy/ai/rag/result.py +78 -0
  35. swiftpy/ai/rag/retriever.py +315 -0
  36. swiftpy/ai/redis_store.py +227 -0
  37. swiftpy/ai/streaming.py +115 -0
  38. swiftpy/ai/tools/__init__.py +22 -0
  39. swiftpy/ai/tools/base_tool.py +489 -0
  40. swiftpy/ai/tools/first_party.py +384 -0
  41. swiftpy/ai/tools/tool_loop.py +417 -0
  42. swiftpy/ai/vectorstore/__init__.py +46 -0
  43. swiftpy/ai/vectorstore/base.py +542 -0
  44. swiftpy/ai/vectorstore/chroma_adapter.py +435 -0
  45. swiftpy/ai/vectorstore/in_memory_adapter.py +321 -0
  46. swiftpy/ai/vectorstore/lancedb_adapter.py +370 -0
  47. swiftpy/ai/vectorstore/pgvector_adapter.py +496 -0
  48. swiftpy/ai/vectorstore/pinecone_adapter.py +445 -0
  49. swiftpy/ai/vectorstore/qdrant_adapter.py +418 -0
  50. swiftpy/auth/__init__.py +50 -0
  51. swiftpy/auth/api_key_guard.py +544 -0
  52. swiftpy/auth/auth_manager.py +259 -0
  53. swiftpy/auth/exceptions.py +71 -0
  54. swiftpy/auth/jwt_guard.py +230 -0
  55. swiftpy/auth/jwt_issuer.py +658 -0
  56. swiftpy/auth/token_blacklist.py +300 -0
  57. swiftpy/cache/__init__.py +14 -0
  58. swiftpy/cache/cache.py +251 -0
  59. swiftpy/cache/driver.py +216 -0
  60. swiftpy/cache/drivers/memory.py +199 -0
  61. swiftpy/cache/drivers/redis.py +421 -0
  62. swiftpy/console/__init__.py +0 -0
  63. swiftpy/console/cli.py +68 -0
  64. swiftpy/console/commands/__init__.py +0 -0
  65. swiftpy/console/commands/cache.py +164 -0
  66. swiftpy/console/commands/make.py +935 -0
  67. swiftpy/console/commands/migrate.py +280 -0
  68. swiftpy/console/commands/new.py +1806 -0
  69. swiftpy/console/commands/queue.py +306 -0
  70. swiftpy/console/commands/seed.py +252 -0
  71. swiftpy/console/commands/start.py +171 -0
  72. swiftpy/console/commands/storage.py +104 -0
  73. swiftpy/console/loader.py +21 -0
  74. swiftpy/console/stubs/__init__.py +26 -0
  75. swiftpy/console/stubs/controller.stub +14 -0
  76. swiftpy/console/stubs/event.stub +14 -0
  77. swiftpy/console/stubs/job.stub +22 -0
  78. swiftpy/console/stubs/listener.stub +14 -0
  79. swiftpy/console/stubs/mail.stub +20 -0
  80. swiftpy/console/stubs/middleware.stub +16 -0
  81. swiftpy/console/stubs/migration.alter.stub +17 -0
  82. swiftpy/console/stubs/migration.api_keys.stub +22 -0
  83. swiftpy/console/stubs/migration.blank.stub +11 -0
  84. swiftpy/console/stubs/migration.create.stub +15 -0
  85. swiftpy/console/stubs/migration.stub +11 -0
  86. swiftpy/console/stubs/migration.update.stub +17 -0
  87. swiftpy/console/stubs/model.stub +17 -0
  88. swiftpy/console/stubs/provider.stub +18 -0
  89. swiftpy/console/stubs/repository.stub +10 -0
  90. swiftpy/console/stubs/request.stub +16 -0
  91. swiftpy/console/stubs/resource.stub +21 -0
  92. swiftpy/console/stubs/schema.stub +12 -0
  93. swiftpy/console/stubs/seeder.stub +14 -0
  94. swiftpy/console/stubs/service.stub +10 -0
  95. swiftpy/core/__init__.py +0 -0
  96. swiftpy/core/application.py +1306 -0
  97. swiftpy/core/bootstrap.py +30 -0
  98. swiftpy/core/config.py +432 -0
  99. swiftpy/core/container.py +596 -0
  100. swiftpy/core/container_exceptions.py +18 -0
  101. swiftpy/core/context.py +148 -0
  102. swiftpy/core/exceptions.py +352 -0
  103. swiftpy/core/providers/base.py +35 -0
  104. swiftpy/database/__init__.py +41 -0
  105. swiftpy/database/exceptions.py +42 -0
  106. swiftpy/database/identifiers.py +105 -0
  107. swiftpy/database/migrations/__init__.py +36 -0
  108. swiftpy/database/migrations/blueprint.py +431 -0
  109. swiftpy/database/migrations/lock.py +104 -0
  110. swiftpy/database/migrations/migration.py +22 -0
  111. swiftpy/database/migrations/migrator.py +507 -0
  112. swiftpy/database/migrations/schema.py +435 -0
  113. swiftpy/database/orm/__init__.py +33 -0
  114. swiftpy/database/orm/fields.py +92 -0
  115. swiftpy/database/orm/model.py +2034 -0
  116. swiftpy/database/orm/registry.py +33 -0
  117. swiftpy/database/orm/relationships.py +836 -0
  118. swiftpy/database/pagination/__init__.py +16 -0
  119. swiftpy/database/pagination/contracts.py +60 -0
  120. swiftpy/database/pagination/paginator.py +112 -0
  121. swiftpy/database/pagination/simple_paginator.py +97 -0
  122. swiftpy/database/pool.py +218 -0
  123. swiftpy/database/query_builder.py +1803 -0
  124. swiftpy/database/seeder.py +39 -0
  125. swiftpy/database/transaction.py +276 -0
  126. swiftpy/events/__init__.py +10 -0
  127. swiftpy/events/dispatcher.py +308 -0
  128. swiftpy/events/redis_bus.py +552 -0
  129. swiftpy/filesystem/__init__.py +227 -0
  130. swiftpy/filesystem/disk.py +378 -0
  131. swiftpy/filesystem/drivers/__init__.py +11 -0
  132. swiftpy/filesystem/drivers/base.py +156 -0
  133. swiftpy/filesystem/drivers/local.py +559 -0
  134. swiftpy/filesystem/drivers/s3.py +655 -0
  135. swiftpy/filesystem/events.py +37 -0
  136. swiftpy/filesystem/exceptions.py +127 -0
  137. swiftpy/filesystem/manager.py +138 -0
  138. swiftpy/filesystem/metadata.py +22 -0
  139. swiftpy/filesystem/paths.py +99 -0
  140. swiftpy/filesystem/service_provider.py +17 -0
  141. swiftpy/filesystem/uploads/__init__.py +13 -0
  142. swiftpy/filesystem/uploads/handlers.py +362 -0
  143. swiftpy/filesystem/uploads/uploaded_file.py +222 -0
  144. swiftpy/filesystem/uploads/validators.py +186 -0
  145. swiftpy/filesystem/visibility.py +22 -0
  146. swiftpy/helpers/__init__.py +42 -0
  147. swiftpy/helpers/helper.py +180 -0
  148. swiftpy/http/exceptions.py +41 -0
  149. swiftpy/http/middleware.py +307 -0
  150. swiftpy/http/request.py +375 -0
  151. swiftpy/http/response.py +442 -0
  152. swiftpy/http/router.py +1050 -0
  153. swiftpy/mail/__init__.py +58 -0
  154. swiftpy/mail/attachments.py +255 -0
  155. swiftpy/mail/config.py +71 -0
  156. swiftpy/mail/envelope.py +183 -0
  157. swiftpy/mail/exceptions.py +90 -0
  158. swiftpy/mail/facade.py +312 -0
  159. swiftpy/mail/mailable.py +53 -0
  160. swiftpy/mail/manager.py +240 -0
  161. swiftpy/mail/message.py +186 -0
  162. swiftpy/mail/models.py +19 -0
  163. swiftpy/mail/queue/__init__.py +5 -0
  164. swiftpy/mail/queue/job.py +279 -0
  165. swiftpy/mail/service_provider.py +19 -0
  166. swiftpy/mail/templates/__init__.py +5 -0
  167. swiftpy/mail/templates/renderer.py +173 -0
  168. swiftpy/mail/transports/__init__.py +21 -0
  169. swiftpy/mail/transports/api/__init__.py +13 -0
  170. swiftpy/mail/transports/api/base.py +194 -0
  171. swiftpy/mail/transports/api/mailgun.py +158 -0
  172. swiftpy/mail/transports/api/resend.py +156 -0
  173. swiftpy/mail/transports/api/sendgrid.py +172 -0
  174. swiftpy/mail/transports/base.py +24 -0
  175. swiftpy/mail/transports/console.py +91 -0
  176. swiftpy/mail/transports/sendmail.py +128 -0
  177. swiftpy/mail/transports/smtp.py +466 -0
  178. swiftpy/queue/__init__.py +13 -0
  179. swiftpy/queue/dispatcher.py +813 -0
  180. swiftpy/queue/job.py +541 -0
  181. swiftpy/queue/worker.py +556 -0
  182. swiftpy/support/__init__.py +12 -0
  183. swiftpy/support/keys.py +108 -0
  184. swiftpy/support/redis_config.py +223 -0
  185. swiftpy/support/strings.py +114 -0
  186. swiftpy/testing/__init__.py +20 -0
  187. swiftpy/testing/fakes/__init__.py +11 -0
  188. swiftpy/testing/fakes/ai_fake.py +21 -0
  189. swiftpy/testing/fakes/vectorstore_fake.py +194 -0
  190. swiftpy/testing/fixtures.py +124 -0
  191. swiftpy/testing/http_client.py +730 -0
  192. swiftpy/testing/test_case.py +126 -0
  193. swiftpy/validation/__init__.py +97 -0
  194. swiftpy/validation/exceptions.py +26 -0
  195. swiftpy/validation/form_request.py +302 -0
  196. swiftpy/validation/protocols.py +33 -0
  197. swiftpy/validation/rules/__init__.py +89 -0
  198. swiftpy/validation/rules/builtin.py +391 -0
  199. swiftpy/validation/rules/exists.py +86 -0
  200. swiftpy/validation/rules/registry.py +290 -0
  201. swiftpy/validation/rules/required.py +55 -0
  202. swiftpy/validation/rules/unique.py +138 -0
  203. swiftpy/validation/validator.py +612 -0
  204. swiftpy/websockets/__init__.py +19 -0
  205. swiftpy/websockets/connection.py +317 -0
  206. swiftpy/websockets/manager.py +271 -0
  207. swiftpy_framework-0.1.0.dist-info/METADATA +603 -0
  208. swiftpy_framework-0.1.0.dist-info/RECORD +211 -0
  209. swiftpy_framework-0.1.0.dist-info/WHEEL +4 -0
  210. swiftpy_framework-0.1.0.dist-info/entry_points.txt +2 -0
  211. swiftpy_framework-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,171 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import sys
5
+ from typing import Any
6
+
7
+ import uvicorn
8
+
9
+ from swiftpy.core.config import Config, ConfigurationError
10
+
11
+
12
+ def _first_configured(*values: Any) -> Any:
13
+ """Return the first explicitly configured value, preserving integer 0 and boolean False."""
14
+ for value in values:
15
+ if value is not None and value != "":
16
+ return value
17
+ return None
18
+
19
+
20
+ class StartCommand:
21
+ @staticmethod
22
+ def register(
23
+ subparsers: argparse._SubParsersAction[argparse.ArgumentParser],
24
+ ) -> None:
25
+ parser = subparsers.add_parser(
26
+ "start",
27
+ help="Boot the application server",
28
+ )
29
+
30
+ parser.add_argument(
31
+ "target",
32
+ nargs="?",
33
+ default=None,
34
+ help="Application ASGI target (default: from config or 'main:app')",
35
+ )
36
+
37
+ parser.add_argument(
38
+ "--host",
39
+ dest="host",
40
+ default=None,
41
+ help="Bind socket to this host (default: from config or '127.0.0.1')",
42
+ )
43
+
44
+ parser.add_argument(
45
+ "--port",
46
+ dest="port",
47
+ type=int,
48
+ default=None,
49
+ help="Bind socket to this port (default: from config or 8000)",
50
+ )
51
+
52
+ parser.add_argument(
53
+ "--workers",
54
+ dest="workers",
55
+ type=int,
56
+ default=None,
57
+ help="Number of worker processes (default: 1)",
58
+ )
59
+
60
+ parser.add_argument(
61
+ "--reload",
62
+ dest="reload",
63
+ action="store_true",
64
+ default=False,
65
+ help="Enable auto-reload on code change (default: False)",
66
+ )
67
+
68
+ parser.add_argument(
69
+ "--env-file",
70
+ dest="env_file",
71
+ default=None,
72
+ help="Environment configuration file path (e.g. '.env')",
73
+ )
74
+
75
+ parser.add_argument(
76
+ "--access-log",
77
+ dest="access_log",
78
+ action=argparse.BooleanOptionalAction,
79
+ default=None,
80
+ help="Enable or disable uvicorn access log",
81
+ )
82
+
83
+ parser.add_argument(
84
+ "--log-level",
85
+ dest="log_level",
86
+ default=None,
87
+ help="Logging level (critical, error, warning, info, debug, trace)",
88
+ )
89
+
90
+ parser.set_defaults(
91
+ _handler=StartCommand.handle,
92
+ )
93
+
94
+ @staticmethod
95
+ def handle(args: argparse.Namespace) -> None:
96
+ try:
97
+ config = Config.load()
98
+ except (ConfigurationError, OSError, ValueError, RuntimeError, SyntaxError):
99
+ config = Config()
100
+
101
+ target = (
102
+ args.target
103
+ or config.get("server.target")
104
+ or config.get("app.target")
105
+ or "main:app"
106
+ )
107
+ host = (
108
+ args.host
109
+ or config.get("server.host")
110
+ or config.get("app.host")
111
+ or "127.0.0.1"
112
+ )
113
+ raw_port = _first_configured(
114
+ args.port,
115
+ config.get("server.port"),
116
+ config.get("app.port"),
117
+ 8000,
118
+ )
119
+ port = int(raw_port)
120
+ if port < 0 or port > 65535:
121
+ sys.stderr.write(
122
+ f"Error: invalid port {port} (must be between 0 and 65535).\n"
123
+ )
124
+ raise SystemExit(1)
125
+
126
+ raw_workers = _first_configured(
127
+ args.workers,
128
+ config.get("server.workers"),
129
+ 1,
130
+ )
131
+ workers = int(raw_workers)
132
+ if workers < 1:
133
+ sys.stderr.write(
134
+ f"Error: invalid worker count {workers} (must be >= 1).\n"
135
+ )
136
+ raise SystemExit(1)
137
+ reload = bool(args.reload)
138
+ env_file = args.env_file or config.get("server.env_file")
139
+
140
+ if reload and workers > 1:
141
+ sys.stderr.write(
142
+ "Error: --reload cannot be used with multiple workers (--workers > 1).\n"
143
+ )
144
+ raise SystemExit(1)
145
+
146
+ uvicorn_kwargs: dict[str, Any] = {
147
+ "host": host,
148
+ "port": port,
149
+ "reload": reload,
150
+ }
151
+ if workers > 1:
152
+ uvicorn_kwargs["workers"] = workers
153
+ if env_file:
154
+ uvicorn_kwargs["env_file"] = env_file
155
+
156
+ access_log_opt = (
157
+ args.access_log
158
+ if getattr(args, "access_log", None) is not None
159
+ else config.get("server.access_log")
160
+ )
161
+ if access_log_opt is not None:
162
+ uvicorn_kwargs["access_log"] = bool(access_log_opt)
163
+
164
+ log_level_opt = getattr(args, "log_level", None) or config.get("server.log_level")
165
+ if log_level_opt:
166
+ uvicorn_kwargs["log_level"] = str(log_level_opt).lower()
167
+
168
+ uvicorn.run(target, **uvicorn_kwargs)
169
+
170
+
171
+ __all__ = ["StartCommand"]
@@ -0,0 +1,104 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import os
5
+ import shutil
6
+ import sys
7
+ from pathlib import Path
8
+
9
+ from swiftpy.core.config import Config
10
+
11
+
12
+ def _paint(text: str, code: str) -> str:
13
+ if sys.stdout.isatty() and "NO_COLOR" not in os.environ:
14
+ return f"\033[{code}m{text}\033[0m"
15
+ return text
16
+
17
+
18
+ class StorageCommand:
19
+ """Console commands for filesystem and storage management."""
20
+
21
+ @staticmethod
22
+ def register(
23
+ subparsers: argparse._SubParsersAction[argparse.ArgumentParser],
24
+ ) -> None:
25
+ link_parser = subparsers.add_parser(
26
+ "storage:link",
27
+ help="Create the symbolic links configured for the application",
28
+ )
29
+ link_parser.add_argument(
30
+ "--force",
31
+ action="store_true",
32
+ help="Recreate existing symbolic links",
33
+ )
34
+ link_parser.set_defaults(_handler=StorageCommand.handle_link)
35
+
36
+ storage_group = subparsers.add_parser(
37
+ "storage",
38
+ help="Manage application storage links and operations",
39
+ )
40
+ storage_sub = storage_group.add_subparsers(
41
+ dest="storage_subcommand",
42
+ required=False,
43
+ )
44
+ sub_link = storage_sub.add_parser(
45
+ "link",
46
+ help="Create the symbolic links configured for the application",
47
+ )
48
+ sub_link.add_argument(
49
+ "--force",
50
+ action="store_true",
51
+ help="Recreate existing symbolic links",
52
+ )
53
+ sub_link.set_defaults(_handler=StorageCommand.handle_link)
54
+
55
+ @staticmethod
56
+ def handle_link(args: argparse.Namespace) -> None:
57
+ force = getattr(args, "force", False)
58
+ try:
59
+ cfg = Config.get_instance()
60
+ target_path = Path(
61
+ str(cfg.get("filesystems.disks.public.root", "storage/app/public"))
62
+ ).resolve()
63
+ except (RuntimeError, ValueError, KeyError):
64
+ target_path = Path("storage/app/public").resolve()
65
+
66
+ link_path = Path("public/storage").resolve()
67
+
68
+ target_path.mkdir(parents=True, exist_ok=True)
69
+ link_path.parent.mkdir(parents=True, exist_ok=True)
70
+
71
+ if link_path.is_symlink() or link_path.exists():
72
+ if force:
73
+ if link_path.is_symlink():
74
+ link_path.unlink()
75
+ elif link_path.is_dir():
76
+ shutil.rmtree(link_path)
77
+ else:
78
+ link_path.unlink()
79
+ else:
80
+ msg = _paint(f"The [{link_path.relative_to(Path.cwd())}] link already exists.", "33")
81
+ print(msg)
82
+ return
83
+
84
+ try:
85
+ os.symlink(target_path, link_path, target_is_directory=True)
86
+ rel_link = (
87
+ link_path.relative_to(Path.cwd())
88
+ if link_path.is_relative_to(Path.cwd())
89
+ else link_path
90
+ )
91
+ rel_target = (
92
+ target_path.relative_to(Path.cwd())
93
+ if target_path.is_relative_to(Path.cwd())
94
+ else target_path
95
+ )
96
+ msg = _paint(
97
+ f"The [{rel_link}] link has been connected to [{rel_target}].",
98
+ "32",
99
+ )
100
+ print(msg)
101
+ except OSError as exc:
102
+ err = _paint(f"Failed to create storage link: {exc}", "31")
103
+ print(err, file=sys.stderr)
104
+ sys.exit(1)
@@ -0,0 +1,21 @@
1
+ from __future__ import annotations
2
+
3
+ import importlib
4
+ import sys
5
+ from pathlib import Path
6
+
7
+ from swiftpy.core.application import Application
8
+
9
+
10
+ def load_application(target: str = "main:app") -> Application:
11
+ """Import `module:attribute` from the current project and return the Application."""
12
+ module_name, _, attribute = target.partition(":")
13
+ project_root = str(Path.cwd())
14
+ if project_root not in sys.path:
15
+ sys.path.insert(0, project_root)
16
+
17
+ module = importlib.import_module(module_name)
18
+ app = getattr(module, attribute or "app")
19
+ if not isinstance(app, Application):
20
+ raise TypeError(f"{target!r} is not a SwiftPY Application")
21
+ return app
@@ -0,0 +1,26 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+
5
+ STUBS_DIR = Path(__file__).resolve().parent
6
+
7
+
8
+ def get_stub(name: str) -> str:
9
+ """
10
+ Load a stub template string by name from the stubs directory.
11
+ Supports both dotted and underscore conventions (e.g. 'migration.create' or 'migration_create').
12
+ """
13
+ cleaned = name.removesuffix(".stub")
14
+ candidates = (
15
+ STUBS_DIR / f"{cleaned}.stub",
16
+ STUBS_DIR / f"{cleaned.replace('_', '.')}.stub",
17
+ STUBS_DIR / f"{cleaned.replace('.', '_')}.stub",
18
+ )
19
+ for path in candidates:
20
+ if path.is_file():
21
+ return path.read_text(encoding="utf-8")
22
+
23
+ raise FileNotFoundError(f"Stub file not found for name '{name}' in {STUBS_DIR}")
24
+
25
+
26
+ __all__ = ["STUBS_DIR", "get_stub"]
@@ -0,0 +1,14 @@
1
+ from __future__ import annotations
2
+
3
+ from swiftpy.http.request import Request
4
+ from swiftpy.http.response import Response, json_response
5
+
6
+
7
+ class {class_name}:
8
+ """
9
+ HTTP Controller for handling request endpoints.
10
+ """
11
+
12
+ async def index(self, request: Request) -> Response:
13
+ return json_response({"message": "Hello from {class_name}"})
14
+
@@ -0,0 +1,14 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any
5
+
6
+
7
+ @dataclass(slots=True, frozen=True)
8
+ class {class_name}:
9
+ """
10
+ Domain event carrying immutable state.
11
+ """
12
+
13
+ payload: dict[str, Any]
14
+
@@ -0,0 +1,22 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from swiftpy.queue.job import Job
6
+
7
+
8
+ class {class_name}(Job):
9
+ """
10
+ Asynchronous queued background job.
11
+ """
12
+
13
+ tries: int = 3
14
+ backoff: int = 5
15
+
16
+ def __init__(self, **payload: Any) -> None:
17
+ self.payload = payload
18
+
19
+ async def handle(self) -> None:
20
+ """Execute the job's background logic."""
21
+ pass
22
+
@@ -0,0 +1,14 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+
6
+ class {class_name}:
7
+ """
8
+ Asynchronous event listener.
9
+ """
10
+
11
+ async def handle(self, event: Any) -> None:
12
+ """Handle the dispatched event."""
13
+ pass
14
+
@@ -0,0 +1,20 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from swiftpy.mail import Mailable, MailMessage
6
+
7
+
8
+ class {class_name}(Mailable):
9
+ """{class_name} mailable definition."""
10
+
11
+ def __init__(self) -> None:
12
+ pass
13
+
14
+ def build(self) -> MailMessage:
15
+ return MailMessage(
16
+ subject="{class_name}",
17
+ to=[],
18
+ text_body="Hello from {class_name}!",
19
+ )
20
+
@@ -0,0 +1,16 @@
1
+ from __future__ import annotations
2
+
3
+ from swiftpy.http.middleware import Handler, Middleware
4
+ from swiftpy.http.request import Request
5
+ from swiftpy.http.response import Response
6
+
7
+
8
+ class {class_name}(Middleware):
9
+ """
10
+ ASGI Middleware for request preprocessing and response handling.
11
+ """
12
+
13
+ async def handle(self, request: Request, next_handler: Handler) -> Response:
14
+ response = await next_handler(request)
15
+ return response
16
+
@@ -0,0 +1,17 @@
1
+ from __future__ import annotations
2
+
3
+ from swiftpy.database.migrations import Blueprint, Migration, Schema
4
+
5
+
6
+ class {class_name}(Migration):
7
+ async def up(self) -> None:
8
+ def define(table: Blueprint) -> None:
9
+ pass # table.string("column_name").nullable()
10
+
11
+ await Schema.table("{table_name}", define)
12
+
13
+ async def down(self) -> None:
14
+ def define(table: Blueprint) -> None:
15
+ pass # table.drop_column("column_name")
16
+
17
+ await Schema.table("{table_name}", define)
@@ -0,0 +1,22 @@
1
+ from __future__ import annotations
2
+
3
+ from swiftpy.database.migrations import Blueprint, Migration, Schema
4
+
5
+
6
+ class {class_name}(Migration):
7
+ async def up(self) -> None:
8
+ def define(table: Blueprint) -> None:
9
+ table.id()
10
+ table.string("name")
11
+ table.string("key_prefix", length=64).unique().index()
12
+ table.string("key_hash", length=128)
13
+ table.boolean("is_active").default(True)
14
+ table.boolean("revoked").default(False)
15
+ table.timestamp("expires_at").nullable()
16
+ table.timestamps()
17
+
18
+ await Schema.create("{table_name}", define)
19
+
20
+ async def down(self) -> None:
21
+ await Schema.drop_if_exists("{table_name}")
22
+
@@ -0,0 +1,11 @@
1
+ from __future__ import annotations
2
+
3
+ from swiftpy.database.migrations import Migration
4
+
5
+
6
+ class {class_name}(Migration):
7
+ async def up(self) -> None:
8
+ pass
9
+
10
+ async def down(self) -> None:
11
+ pass
@@ -0,0 +1,15 @@
1
+ from __future__ import annotations
2
+
3
+ from swiftpy.database.migrations import Blueprint, Migration, Schema
4
+
5
+
6
+ class {class_name}(Migration):
7
+ async def up(self) -> None:
8
+ def define(table: Blueprint) -> None:
9
+ table.id()
10
+ table.timestamps()
11
+
12
+ await Schema.create("{table_name}", define)
13
+
14
+ async def down(self) -> None:
15
+ await Schema.drop_if_exists("{table_name}")
@@ -0,0 +1,11 @@
1
+ from __future__ import annotations
2
+
3
+ from swiftpy.database.migrations import Migration
4
+
5
+
6
+ class {class_name}(Migration):
7
+ async def up(self) -> None:
8
+ pass
9
+
10
+ async def down(self) -> None:
11
+ pass
@@ -0,0 +1,17 @@
1
+ from __future__ import annotations
2
+
3
+ from swiftpy.database.migrations import Blueprint, Migration, Schema
4
+
5
+
6
+ class {class_name}(Migration):
7
+ async def up(self) -> None:
8
+ def define(table: Blueprint) -> None:
9
+ pass # table.string("column_name").nullable()
10
+
11
+ await Schema.table("{table_name}", define)
12
+
13
+ async def down(self) -> None:
14
+ def define(table: Blueprint) -> None:
15
+ pass # table.drop_column("column_name")
16
+
17
+ await Schema.table("{table_name}", define)
@@ -0,0 +1,17 @@
1
+ from __future__ import annotations
2
+
3
+ from datetime import datetime
4
+ from typing import ClassVar
5
+
6
+ from swiftpy.database.orm import Model
7
+
8
+
9
+ class {class_name}(Model):
10
+ """{class_name} model."""
11
+
12
+ __table__ = "{table_name}"
13
+ __fillable__: ClassVar[list[str]] = []
14
+
15
+ id: int
16
+ created_at: datetime
17
+ updated_at: datetime
@@ -0,0 +1,18 @@
1
+ from __future__ import annotations
2
+
3
+ from swiftpy.core.providers.base import ServiceProvider
4
+
5
+
6
+ class {class_name}(ServiceProvider):
7
+ """
8
+ Modular application service provider.
9
+ """
10
+
11
+ def register(self) -> None:
12
+ """Bind services and interfaces into the DI container."""
13
+ pass
14
+
15
+ def boot(self) -> None:
16
+ """Boot application services, attach listeners, and warm caches."""
17
+ pass
18
+
@@ -0,0 +1,10 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+
6
+ class {class_name}:
7
+ """{class_name} data access repository."""
8
+
9
+ def __init__(self) -> None:
10
+ pass
@@ -0,0 +1,16 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from swiftpy.validation.form_request import FormRequest
6
+
7
+
8
+ class {class_name}(FormRequest):
9
+ """{class_name} validation request."""
10
+
11
+ def rules(self) -> dict[str, Any]:
12
+ """Define validation rules for the incoming request."""
13
+ return {
14
+ # "email": "required|email",
15
+ # "password": "required|min:8",
16
+ }
@@ -0,0 +1,21 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+
6
+ class {class_name}:
7
+ """{class_name} API resource transformer."""
8
+
9
+ def __init__(self, resource: Any) -> None:
10
+ self.resource = resource
11
+
12
+ def to_dict(self) -> dict[str, Any]:
13
+ """Transform the resource into an array/dict."""
14
+ return {
15
+ "id": getattr(self.resource, "id", None),
16
+ }
17
+
18
+ @classmethod
19
+ def collection(cls, items: list[Any]) -> list[dict[str, Any]]:
20
+ """Transform a collection of resources."""
21
+ return [cls(item).to_dict() for item in items]
@@ -0,0 +1,12 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+
6
+ class {class_name}:
7
+ """{class_name} data schema."""
8
+
9
+ schema: dict[str, Any] = {
10
+ # "id": int,
11
+ # "name": str,
12
+ }
@@ -0,0 +1,14 @@
1
+ from __future__ import annotations
2
+
3
+ from swiftpy.database.seeder import Seeder
4
+
5
+
6
+ class {class_name}(Seeder):
7
+ """
8
+ Database seeder for generating and seeding records.
9
+ """
10
+
11
+ async def run(self) -> None:
12
+ """Execute the database seed operations."""
13
+ pass
14
+
@@ -0,0 +1,10 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+
6
+ class {class_name}:
7
+ """{class_name} service."""
8
+
9
+ def __init__(self) -> None:
10
+ pass
File without changes