infomankit 0.3.23__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.
- infoman/__init__.py +1 -0
- infoman/cli/README.md +378 -0
- infoman/cli/__init__.py +7 -0
- infoman/cli/commands/__init__.py +3 -0
- infoman/cli/commands/init.py +312 -0
- infoman/cli/scaffold.py +634 -0
- infoman/cli/templates/Makefile.template +132 -0
- infoman/cli/templates/app/__init__.py.template +3 -0
- infoman/cli/templates/app/app.py.template +4 -0
- infoman/cli/templates/app/models_base.py.template +18 -0
- infoman/cli/templates/app/models_entity_init.py.template +11 -0
- infoman/cli/templates/app/models_schemas_init.py.template +11 -0
- infoman/cli/templates/app/repository_init.py.template +11 -0
- infoman/cli/templates/app/routers_init.py.template +15 -0
- infoman/cli/templates/app/services_init.py.template +11 -0
- infoman/cli/templates/app/static_index.html.template +39 -0
- infoman/cli/templates/app/static_main.js.template +31 -0
- infoman/cli/templates/app/static_style.css.template +111 -0
- infoman/cli/templates/app/utils_init.py.template +11 -0
- infoman/cli/templates/config/.env.dev.template +43 -0
- infoman/cli/templates/config/.env.prod.template +43 -0
- infoman/cli/templates/config/README.md.template +28 -0
- infoman/cli/templates/docker/.dockerignore.template +60 -0
- infoman/cli/templates/docker/Dockerfile.template +47 -0
- infoman/cli/templates/docker/README.md.template +240 -0
- infoman/cli/templates/docker/docker-compose.yml.template +81 -0
- infoman/cli/templates/docker/mysql_custom.cnf.template +42 -0
- infoman/cli/templates/docker/mysql_init.sql.template +15 -0
- infoman/cli/templates/project/.env.example.template +1 -0
- infoman/cli/templates/project/.gitignore.template +60 -0
- infoman/cli/templates/project/Makefile.template +38 -0
- infoman/cli/templates/project/README.md.template +137 -0
- infoman/cli/templates/project/deploy.sh.template +97 -0
- infoman/cli/templates/project/main.py.template +10 -0
- infoman/cli/templates/project/manage.sh.template +97 -0
- infoman/cli/templates/project/pyproject.toml.template +47 -0
- infoman/cli/templates/project/service.sh.template +203 -0
- infoman/config/__init__.py +25 -0
- infoman/config/base.py +67 -0
- infoman/config/db_cache.py +237 -0
- infoman/config/db_relation.py +181 -0
- infoman/config/db_vector.py +39 -0
- infoman/config/jwt.py +16 -0
- infoman/config/llm.py +16 -0
- infoman/config/log.py +627 -0
- infoman/config/mq.py +26 -0
- infoman/config/settings.py +65 -0
- infoman/llm/__init__.py +0 -0
- infoman/llm/llm.py +297 -0
- infoman/logger/__init__.py +57 -0
- infoman/logger/context.py +191 -0
- infoman/logger/core.py +358 -0
- infoman/logger/filters.py +157 -0
- infoman/logger/formatters.py +138 -0
- infoman/logger/handlers.py +276 -0
- infoman/logger/metrics.py +160 -0
- infoman/performance/README.md +583 -0
- infoman/performance/__init__.py +19 -0
- infoman/performance/cli.py +215 -0
- infoman/performance/config.py +166 -0
- infoman/performance/reporter.py +519 -0
- infoman/performance/runner.py +303 -0
- infoman/performance/standards.py +222 -0
- infoman/service/__init__.py +8 -0
- infoman/service/app.py +67 -0
- infoman/service/core/__init__.py +0 -0
- infoman/service/core/auth.py +105 -0
- infoman/service/core/lifespan.py +132 -0
- infoman/service/core/monitor.py +57 -0
- infoman/service/core/response.py +37 -0
- infoman/service/exception/__init__.py +7 -0
- infoman/service/exception/error.py +274 -0
- infoman/service/exception/exception.py +25 -0
- infoman/service/exception/handler.py +238 -0
- infoman/service/infrastructure/__init__.py +8 -0
- infoman/service/infrastructure/base.py +212 -0
- infoman/service/infrastructure/db_cache/__init__.py +8 -0
- infoman/service/infrastructure/db_cache/manager.py +194 -0
- infoman/service/infrastructure/db_relation/__init__.py +41 -0
- infoman/service/infrastructure/db_relation/manager.py +300 -0
- infoman/service/infrastructure/db_relation/manager_pro.py +408 -0
- infoman/service/infrastructure/db_relation/mysql.py +52 -0
- infoman/service/infrastructure/db_relation/pgsql.py +54 -0
- infoman/service/infrastructure/db_relation/sqllite.py +25 -0
- infoman/service/infrastructure/db_vector/__init__.py +40 -0
- infoman/service/infrastructure/db_vector/manager.py +201 -0
- infoman/service/infrastructure/db_vector/qdrant.py +322 -0
- infoman/service/infrastructure/mq/__init__.py +15 -0
- infoman/service/infrastructure/mq/manager.py +178 -0
- infoman/service/infrastructure/mq/nats/__init__.py +0 -0
- infoman/service/infrastructure/mq/nats/nats_client.py +57 -0
- infoman/service/infrastructure/mq/nats/nats_event_router.py +25 -0
- infoman/service/launch.py +284 -0
- infoman/service/middleware/__init__.py +7 -0
- infoman/service/middleware/base.py +41 -0
- infoman/service/middleware/logging.py +51 -0
- infoman/service/middleware/rate_limit.py +301 -0
- infoman/service/middleware/request_id.py +21 -0
- infoman/service/middleware/white_list.py +24 -0
- infoman/service/models/__init__.py +8 -0
- infoman/service/models/base.py +441 -0
- infoman/service/models/type/embed.py +70 -0
- infoman/service/routers/__init__.py +18 -0
- infoman/service/routers/health_router.py +311 -0
- infoman/service/routers/monitor_router.py +44 -0
- infoman/service/utils/__init__.py +8 -0
- infoman/service/utils/cache/__init__.py +0 -0
- infoman/service/utils/cache/cache.py +192 -0
- infoman/service/utils/module_loader.py +10 -0
- infoman/service/utils/parse.py +10 -0
- infoman/service/utils/resolver/__init__.py +8 -0
- infoman/service/utils/resolver/base.py +47 -0
- infoman/service/utils/resolver/resp.py +102 -0
- infoman/service/vector/__init__.py +20 -0
- infoman/service/vector/base.py +56 -0
- infoman/service/vector/qdrant.py +125 -0
- infoman/service/vector/service.py +67 -0
- infoman/utils/__init__.py +2 -0
- infoman/utils/decorators/__init__.py +8 -0
- infoman/utils/decorators/cache.py +137 -0
- infoman/utils/decorators/retry.py +99 -0
- infoman/utils/decorators/safe_execute.py +99 -0
- infoman/utils/decorators/timing.py +99 -0
- infoman/utils/encryption/__init__.py +8 -0
- infoman/utils/encryption/aes.py +66 -0
- infoman/utils/encryption/ecc.py +108 -0
- infoman/utils/encryption/rsa.py +112 -0
- infoman/utils/file/__init__.py +0 -0
- infoman/utils/file/handler.py +22 -0
- infoman/utils/hash/__init__.py +0 -0
- infoman/utils/hash/hash.py +61 -0
- infoman/utils/http/__init__.py +8 -0
- infoman/utils/http/client.py +62 -0
- infoman/utils/http/info.py +94 -0
- infoman/utils/http/result.py +19 -0
- infoman/utils/notification/__init__.py +8 -0
- infoman/utils/notification/feishu.py +35 -0
- infoman/utils/text/__init__.py +8 -0
- infoman/utils/text/extractor.py +111 -0
- infomankit-0.3.23.dist-info/METADATA +632 -0
- infomankit-0.3.23.dist-info/RECORD +143 -0
- infomankit-0.3.23.dist-info/WHEEL +4 -0
- infomankit-0.3.23.dist-info/entry_points.txt +5 -0
infoman/cli/scaffold.py
ADDED
|
@@ -0,0 +1,634 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Project scaffolding generator
|
|
3
|
+
|
|
4
|
+
Generates standard project structure based on infoman/service architecture.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Optional, Dict, Any
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ProjectScaffold:
|
|
13
|
+
"""Project structure generator based on infoman/service standard"""
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
def _get_templates_dir() -> Path:
|
|
17
|
+
"""Get the templates directory path"""
|
|
18
|
+
return Path(__file__).parent / "templates"
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def _load_template(template_path: str) -> str:
|
|
22
|
+
"""
|
|
23
|
+
Load a template file from the templates directory
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
template_path: Relative path to template file (e.g., "app/app.py.template")
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
Template content as string
|
|
30
|
+
"""
|
|
31
|
+
templates_dir = ProjectScaffold._get_templates_dir()
|
|
32
|
+
full_path = templates_dir / template_path
|
|
33
|
+
|
|
34
|
+
if not full_path.exists():
|
|
35
|
+
raise FileNotFoundError(f"Template file not found: {full_path}")
|
|
36
|
+
|
|
37
|
+
return full_path.read_text(encoding="utf-8")
|
|
38
|
+
|
|
39
|
+
@staticmethod
|
|
40
|
+
def _build_structure_from_templates() -> Dict[str, Any]:
|
|
41
|
+
"""
|
|
42
|
+
Build STRUCTURE dictionary by loading from template files
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Dictionary representing the app/ directory structure
|
|
46
|
+
"""
|
|
47
|
+
return {
|
|
48
|
+
"__init__.py": ProjectScaffold._load_template("app/__init__.py.template"),
|
|
49
|
+
"app.py": ProjectScaffold._load_template("app/app.py.template"),
|
|
50
|
+
"models": {
|
|
51
|
+
"__init__.py": '"""\nData models\n"""\n',
|
|
52
|
+
"base.py": ProjectScaffold._load_template("app/models_base.py.template"),
|
|
53
|
+
"entity": {
|
|
54
|
+
"__init__.py": ProjectScaffold._load_template("app/models_entity_init.py.template"),
|
|
55
|
+
},
|
|
56
|
+
"schemas": {
|
|
57
|
+
"__init__.py": ProjectScaffold._load_template("app/models_schemas_init.py.template"),
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
"routers": {
|
|
61
|
+
"__init__.py": ProjectScaffold._load_template("app/routers_init.py.template"),
|
|
62
|
+
},
|
|
63
|
+
"services": {
|
|
64
|
+
"__init__.py": ProjectScaffold._load_template("app/services_init.py.template"),
|
|
65
|
+
},
|
|
66
|
+
"repository": {
|
|
67
|
+
"__init__.py": ProjectScaffold._load_template("app/repository_init.py.template"),
|
|
68
|
+
},
|
|
69
|
+
"utils": {
|
|
70
|
+
"__init__.py": ProjectScaffold._load_template("app/utils_init.py.template"),
|
|
71
|
+
},
|
|
72
|
+
"static": {
|
|
73
|
+
"css": {
|
|
74
|
+
"style.css": ProjectScaffold._load_template("app/static_style.css.template"),
|
|
75
|
+
},
|
|
76
|
+
"js": {
|
|
77
|
+
"main.js": ProjectScaffold._load_template("app/static_main.js.template"),
|
|
78
|
+
},
|
|
79
|
+
"images": {},
|
|
80
|
+
"index.html": ProjectScaffold._load_template("app/static_index.html.template"),
|
|
81
|
+
},
|
|
82
|
+
"template": {},
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@staticmethod
|
|
86
|
+
def _build_config_structure_from_templates() -> Dict[str, str]:
|
|
87
|
+
"""
|
|
88
|
+
Build CONFIG_STRUCTURE dictionary by loading from template files
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
Dictionary representing the config/ directory structure
|
|
92
|
+
"""
|
|
93
|
+
return {
|
|
94
|
+
".env.dev": ProjectScaffold._load_template("config/.env.dev.template"),
|
|
95
|
+
".env.prod": ProjectScaffold._load_template("config/.env.prod.template"),
|
|
96
|
+
"README.md": ProjectScaffold._load_template("config/README.md.template"),
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
# 标准项目目录结构(基于用户需求的 app 结构)
|
|
100
|
+
# STRUCTURE is built dynamically from template files
|
|
101
|
+
STRUCTURE = None # Will be initialized in __init__
|
|
102
|
+
|
|
103
|
+
# Add config directory structure
|
|
104
|
+
CONFIG_STRUCTURE = None # Will be initialized in __init__
|
|
105
|
+
|
|
106
|
+
# Old CONFIG_STRUCTURE (kept for reference, will be removed)
|
|
107
|
+
_OLD_CONFIG_STRUCTURE = {
|
|
108
|
+
".env.dev": """# Application Settings
|
|
109
|
+
APP_NAME={project_name}
|
|
110
|
+
APP_ENV=dev
|
|
111
|
+
APP_PORT=8000
|
|
112
|
+
APP_DEBUG=true
|
|
113
|
+
|
|
114
|
+
LOG_DIR=logs
|
|
115
|
+
LOG_LEVEL=DEBUG
|
|
116
|
+
LOG_FORMAT=simple
|
|
117
|
+
|
|
118
|
+
USE_TEMPLATES=1
|
|
119
|
+
USE_PRO_ORM=1
|
|
120
|
+
TEMPLATE_DIR=./app/template
|
|
121
|
+
#USE_STATIC=1
|
|
122
|
+
|
|
123
|
+
# Database Configuration (infomankit format)
|
|
124
|
+
MYSQL_ENABLED=true
|
|
125
|
+
MYSQL_HOST=127.0.0.1
|
|
126
|
+
MYSQL_PORT=3306
|
|
127
|
+
MYSQL_DB=XXX
|
|
128
|
+
MYSQL_USER=XXX
|
|
129
|
+
MYSQL_PASSWORD=XXX
|
|
130
|
+
MYSQL_CHARSET=utf8mb4
|
|
131
|
+
MYSQL_POOL_MAX_SIZE=10
|
|
132
|
+
MYSQL_POOL_RECYCLE=3600
|
|
133
|
+
MYSQL_ECHO=false
|
|
134
|
+
MYSQL_MODELS_PATH=app.models
|
|
135
|
+
MYSQL_MODELS=entity
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
# JWT Configuration
|
|
139
|
+
JWT_SECRET_KEY=your-secret-key-change-this-in-production
|
|
140
|
+
JWT_ALGORITHM=HS256
|
|
141
|
+
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=30
|
|
142
|
+
|
|
143
|
+
# CORS Configuration (comma-separated origins)
|
|
144
|
+
CORS_ORIGINS=http://localhost:3000,http://localhost:8000
|
|
145
|
+
|
|
146
|
+
# Redis Configuration (Optional)
|
|
147
|
+
REDIS_HOST=localhost
|
|
148
|
+
REDIS_PORT=6379
|
|
149
|
+
REDIS_DB=0
|
|
150
|
+
REDIS_PASSWORD=
|
|
151
|
+
""",
|
|
152
|
+
".env.prod": """# Application Settings
|
|
153
|
+
APP_NAME={project_name}
|
|
154
|
+
APP_ENV=prod
|
|
155
|
+
APP_PORT=8000
|
|
156
|
+
APP_DEBUG=false
|
|
157
|
+
|
|
158
|
+
LOG_DIR=logs
|
|
159
|
+
LOG_LEVEL=INFO
|
|
160
|
+
LOG_FORMAT=json
|
|
161
|
+
|
|
162
|
+
USE_TEMPLATES=1
|
|
163
|
+
USE_PRO_ORM=1
|
|
164
|
+
TEMPLATE_DIR=./app/template
|
|
165
|
+
#USE_STATIC=1
|
|
166
|
+
|
|
167
|
+
# Database Configuration (infomankit format)
|
|
168
|
+
MYSQL_ENABLED=true
|
|
169
|
+
MYSQL_HOST=127.0.0.1
|
|
170
|
+
MYSQL_PORT=3306
|
|
171
|
+
MYSQL_DB=XXX
|
|
172
|
+
MYSQL_USER=XXX
|
|
173
|
+
MYSQL_PASSWORD=XXX
|
|
174
|
+
MYSQL_CHARSET=utf8mb4
|
|
175
|
+
MYSQL_POOL_MAX_SIZE=20
|
|
176
|
+
MYSQL_POOL_RECYCLE=3600
|
|
177
|
+
MYSQL_ECHO=false
|
|
178
|
+
MYSQL_MODELS_PATH=app.models
|
|
179
|
+
MYSQL_MODELS=entity
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
# JWT Configuration
|
|
183
|
+
JWT_SECRET_KEY=your-secret-key-change-this-in-production
|
|
184
|
+
JWT_ALGORITHM=HS256
|
|
185
|
+
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=30
|
|
186
|
+
|
|
187
|
+
# CORS Configuration (comma-separated origins)
|
|
188
|
+
CORS_ORIGINS=https://your-domain.com
|
|
189
|
+
|
|
190
|
+
# Redis Configuration (Optional)
|
|
191
|
+
REDIS_HOST=localhost
|
|
192
|
+
REDIS_PORT=6379
|
|
193
|
+
REDIS_DB=0
|
|
194
|
+
REDIS_PASSWORD=
|
|
195
|
+
""",
|
|
196
|
+
"README.md": """# Configuration Files
|
|
197
|
+
|
|
198
|
+
Environment-specific configuration files for {project_name}.
|
|
199
|
+
|
|
200
|
+
## Available Configurations
|
|
201
|
+
|
|
202
|
+
- `.env.dev` - Development environment configuration
|
|
203
|
+
- `.env.prod` - Production environment configuration
|
|
204
|
+
|
|
205
|
+
## Usage
|
|
206
|
+
|
|
207
|
+
Copy the appropriate config file to your project root as `.env`:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
# For development
|
|
211
|
+
cp config/.env.dev .env
|
|
212
|
+
|
|
213
|
+
# For production
|
|
214
|
+
cp config/.env.prod .env
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Then edit `.env` with your actual values.
|
|
218
|
+
|
|
219
|
+
## Configuration Variables
|
|
220
|
+
|
|
221
|
+
- **APP_NAME**: Application name
|
|
222
|
+
- **APP_ENV**: Environment (dev/prod)
|
|
223
|
+
- **APP_PORT**: Server port
|
|
224
|
+
- **APP_DEBUG**: Debug mode (true/false)
|
|
225
|
+
- **LOG_LEVEL**: Logging level (DEBUG/INFO/WARNING/ERROR)
|
|
226
|
+
- **MYSQL_***: MySQL database configuration
|
|
227
|
+
- **JWT_***: JWT authentication settings
|
|
228
|
+
- **CORS_ORIGINS**: Allowed CORS origins
|
|
229
|
+
- **REDIS_***: Redis configuration (optional)
|
|
230
|
+
""",
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
def __init__(self, project_name: str, target_dir: Optional[Path] = None):
|
|
234
|
+
"""
|
|
235
|
+
初始化项目脚手架
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
project_name: 项目名称
|
|
239
|
+
target_dir: 目标目录,默认为当前目录下的项目名称目录
|
|
240
|
+
"""
|
|
241
|
+
self.project_name = project_name
|
|
242
|
+
self.target_dir = target_dir or Path.cwd() / project_name
|
|
243
|
+
|
|
244
|
+
# Initialize structures from templates
|
|
245
|
+
if ProjectScaffold.STRUCTURE is None:
|
|
246
|
+
ProjectScaffold.STRUCTURE = ProjectScaffold._build_structure_from_templates()
|
|
247
|
+
if ProjectScaffold.CONFIG_STRUCTURE is None:
|
|
248
|
+
ProjectScaffold.CONFIG_STRUCTURE = ProjectScaffold._build_config_structure_from_templates()
|
|
249
|
+
|
|
250
|
+
def create_structure(self, structure: dict, parent_path: Path) -> None:
|
|
251
|
+
"""
|
|
252
|
+
递归创建目录结构
|
|
253
|
+
|
|
254
|
+
Args:
|
|
255
|
+
structure: 目录结构字典
|
|
256
|
+
parent_path: 父目录路径
|
|
257
|
+
"""
|
|
258
|
+
for name, content in structure.items():
|
|
259
|
+
current_path = parent_path / name
|
|
260
|
+
|
|
261
|
+
if isinstance(content, dict):
|
|
262
|
+
# 创建目录
|
|
263
|
+
current_path.mkdir(parents=True, exist_ok=True)
|
|
264
|
+
# 递归创建子结构
|
|
265
|
+
self.create_structure(content, current_path)
|
|
266
|
+
else:
|
|
267
|
+
# 创建文件
|
|
268
|
+
current_path.parent.mkdir(parents=True, exist_ok=True)
|
|
269
|
+
# Format content with project name
|
|
270
|
+
formatted_content = content.format(project_name=self.project_name)
|
|
271
|
+
with open(current_path, "w", encoding="utf-8") as f:
|
|
272
|
+
f.write(formatted_content)
|
|
273
|
+
|
|
274
|
+
def create_config_files(self) -> None:
|
|
275
|
+
"""创建配置文件"""
|
|
276
|
+
# .env
|
|
277
|
+
env_template = self._load_template("project/.env.example.template")
|
|
278
|
+
(self.target_dir / ".env").write_text(
|
|
279
|
+
env_template.format(project_name=self.project_name),
|
|
280
|
+
encoding="utf-8"
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
# pyproject.toml
|
|
284
|
+
pyproject_template = self._load_template("project/pyproject.toml.template")
|
|
285
|
+
(self.target_dir / "pyproject.toml").write_text(
|
|
286
|
+
pyproject_template.format(project_name=self.project_name),
|
|
287
|
+
encoding="utf-8"
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
# README.md
|
|
291
|
+
readme_template = self._load_template("project/README.md.template")
|
|
292
|
+
(self.target_dir / "README.md").write_text(
|
|
293
|
+
readme_template.format(project_name=self.project_name),
|
|
294
|
+
encoding="utf-8"
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
# Create doc directory structure
|
|
298
|
+
doc_dir = self.target_dir / "doc"
|
|
299
|
+
doc_dir.mkdir(exist_ok=True)
|
|
300
|
+
|
|
301
|
+
# Create API documentation template
|
|
302
|
+
api_doc = """# API 开发指南
|
|
303
|
+
|
|
304
|
+
## 快速开始
|
|
305
|
+
|
|
306
|
+
本文档介绍如何使用 {project_name} 开发 API。
|
|
307
|
+
|
|
308
|
+
## 数据流程
|
|
309
|
+
|
|
310
|
+
1. **定义数据模型** (`models/entity/`) - 数据库 ORM 模型
|
|
311
|
+
2. **创建 DTO** (`models/dto/`) - API 请求/响应模型
|
|
312
|
+
3. **实现 Repository** (`repository/`) - 数据访问层
|
|
313
|
+
4. **编写 Service** (`services/`) - 业务逻辑
|
|
314
|
+
5. **添加 Router** (`routers/`) - API 端点
|
|
315
|
+
|
|
316
|
+
## 示例:用户管理 API
|
|
317
|
+
|
|
318
|
+
### 1. 定义 Entity (models/entity/user.py)
|
|
319
|
+
|
|
320
|
+
```python
|
|
321
|
+
from infoman.service.models.base import BaseModel
|
|
322
|
+
from sqlalchemy import Column, String, Integer
|
|
323
|
+
|
|
324
|
+
class User(BaseModel):
|
|
325
|
+
__tablename__ = "users"
|
|
326
|
+
|
|
327
|
+
id = Column(Integer, primary_key=True)
|
|
328
|
+
name = Column(String(100), nullable=False)
|
|
329
|
+
email = Column(String(100), unique=True)
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### 2. 创建 DTO (models/dto/user.py)
|
|
333
|
+
|
|
334
|
+
```python
|
|
335
|
+
from pydantic import BaseModel, EmailStr
|
|
336
|
+
|
|
337
|
+
class UserCreateDTO(BaseModel):
|
|
338
|
+
name: str
|
|
339
|
+
email: EmailStr
|
|
340
|
+
|
|
341
|
+
class UserResponseDTO(BaseModel):
|
|
342
|
+
id: int
|
|
343
|
+
name: str
|
|
344
|
+
email: str
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### 3. 实现 Repository (repository/user_repository.py)
|
|
348
|
+
|
|
349
|
+
```python
|
|
350
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
351
|
+
from models.entity.user import User
|
|
352
|
+
from models.dto.user import UserCreateDTO
|
|
353
|
+
|
|
354
|
+
class UserRepository:
|
|
355
|
+
def __init__(self, session: AsyncSession):
|
|
356
|
+
self.session = session
|
|
357
|
+
|
|
358
|
+
async def create(self, data: UserCreateDTO) -> User:
|
|
359
|
+
user = User(**data.model_dump())
|
|
360
|
+
self.session.add(user)
|
|
361
|
+
await self.session.commit()
|
|
362
|
+
return user
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### 4. 创建 Service (services/user_service.py)
|
|
366
|
+
|
|
367
|
+
```python
|
|
368
|
+
from repository.user_repository import UserRepository
|
|
369
|
+
from models.dto.user import UserCreateDTO, UserResponseDTO
|
|
370
|
+
|
|
371
|
+
class UserService:
|
|
372
|
+
def __init__(self, repo: UserRepository):
|
|
373
|
+
self.repo = repo
|
|
374
|
+
|
|
375
|
+
async def create_user(self, data: UserCreateDTO) -> UserResponseDTO:
|
|
376
|
+
user = await self.repo.create(data)
|
|
377
|
+
return UserResponseDTO(
|
|
378
|
+
id=user.id,
|
|
379
|
+
name=user.name,
|
|
380
|
+
email=user.email
|
|
381
|
+
)
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### 5. 添加 Router (routers/user_router.py)
|
|
385
|
+
|
|
386
|
+
```python
|
|
387
|
+
from fastapi import APIRouter, Depends
|
|
388
|
+
from models.dto.user import UserCreateDTO, UserResponseDTO
|
|
389
|
+
from services.user_service import UserService
|
|
390
|
+
|
|
391
|
+
router = APIRouter(prefix="/users", tags=["Users"])
|
|
392
|
+
|
|
393
|
+
@router.post("/", response_model=UserResponseDTO)
|
|
394
|
+
async def create_user(
|
|
395
|
+
data: UserCreateDTO,
|
|
396
|
+
service: UserService = Depends()
|
|
397
|
+
):
|
|
398
|
+
return await service.create_user(data)
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### 6. 注册 Router (routers/__init__.py)
|
|
402
|
+
|
|
403
|
+
```python
|
|
404
|
+
from .user_router import router as user_router
|
|
405
|
+
|
|
406
|
+
api_router.include_router(user_router)
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
## 更多信息
|
|
410
|
+
|
|
411
|
+
查看 infomankit 文档:https://github.com/infoman-lib/infoman-pykit
|
|
412
|
+
""".format(project_name=self.project_name)
|
|
413
|
+
|
|
414
|
+
(doc_dir / "1-API-GUIDE.md").write_text(api_doc, encoding="utf-8")
|
|
415
|
+
|
|
416
|
+
# Create deployment guide
|
|
417
|
+
deploy_doc = """# 部署指南
|
|
418
|
+
|
|
419
|
+
## Docker 部署(推荐)
|
|
420
|
+
|
|
421
|
+
### 1. 构建镜像
|
|
422
|
+
|
|
423
|
+
```bash
|
|
424
|
+
make docker-build
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### 2. 启动服务
|
|
428
|
+
|
|
429
|
+
```bash
|
|
430
|
+
make docker-up
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### 3. 查看日志
|
|
434
|
+
|
|
435
|
+
```bash
|
|
436
|
+
make docker-logs
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### 4. 停止服务
|
|
440
|
+
|
|
441
|
+
```bash
|
|
442
|
+
make docker-down
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
## 本地部署
|
|
446
|
+
|
|
447
|
+
### 1. 安装依赖
|
|
448
|
+
|
|
449
|
+
```bash
|
|
450
|
+
make install
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### 2. 配置环境
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
make init-env
|
|
457
|
+
# 编辑 .env 文件
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### 3. 运行服务
|
|
461
|
+
|
|
462
|
+
```bash
|
|
463
|
+
# 开发模式
|
|
464
|
+
make dev
|
|
465
|
+
|
|
466
|
+
# 生产模式
|
|
467
|
+
make run
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
## 生产环境建议
|
|
471
|
+
|
|
472
|
+
- 使用环境变量管理配置
|
|
473
|
+
- 配置反向代理(Nginx/Caddy)
|
|
474
|
+
- 启用 HTTPS
|
|
475
|
+
- 设置日志轮转
|
|
476
|
+
- 配置健康检查
|
|
477
|
+
- 使用进程管理器(systemd/supervisor)
|
|
478
|
+
|
|
479
|
+
## 监控
|
|
480
|
+
|
|
481
|
+
访问以下端点检查服务状态:
|
|
482
|
+
|
|
483
|
+
- `/health` - 健康检查
|
|
484
|
+
- `/api/docs` - API 文档
|
|
485
|
+
- `/metrics` - Prometheus 指标(如已启用)
|
|
486
|
+
"""
|
|
487
|
+
|
|
488
|
+
(doc_dir / "2-DEPLOYMENT.md").write_text(deploy_doc, encoding="utf-8")
|
|
489
|
+
|
|
490
|
+
# main.py
|
|
491
|
+
main_py_template = self._load_template("project/main.py.template")
|
|
492
|
+
(self.target_dir / "main.py").write_text(
|
|
493
|
+
main_py_template.format(project_name=self.project_name),
|
|
494
|
+
encoding="utf-8"
|
|
495
|
+
)
|
|
496
|
+
|
|
497
|
+
# .gitignore
|
|
498
|
+
gitignore_template = self._load_template("project/.gitignore.template")
|
|
499
|
+
(self.target_dir / ".gitignore").write_text(
|
|
500
|
+
gitignore_template.format(project_name=self.project_name),
|
|
501
|
+
encoding="utf-8"
|
|
502
|
+
)
|
|
503
|
+
|
|
504
|
+
def create_makefile(self) -> None:
|
|
505
|
+
"""创建 Makefile"""
|
|
506
|
+
makefile_template = self._load_template("project/Makefile.template")
|
|
507
|
+
(self.target_dir / "Makefile").write_text(
|
|
508
|
+
makefile_template.format(project_name=self.project_name),
|
|
509
|
+
encoding="utf-8"
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
def create_service_script(self) -> None:
|
|
513
|
+
"""创建 service.sh 服务管理脚本"""
|
|
514
|
+
service_sh_template = self._load_template("project/service.sh.template")
|
|
515
|
+
service_path = self.target_dir / "service.sh"
|
|
516
|
+
service_path.write_text(
|
|
517
|
+
service_sh_template.format(project_name=self.project_name),
|
|
518
|
+
encoding="utf-8"
|
|
519
|
+
)
|
|
520
|
+
# Make executable
|
|
521
|
+
import os
|
|
522
|
+
os.chmod(service_path, 0o755)
|
|
523
|
+
|
|
524
|
+
def generate_docker_files(self) -> None:
|
|
525
|
+
"""生成 Docker 相关文件到 /docker 目录"""
|
|
526
|
+
docker_dir = self.target_dir / "docker"
|
|
527
|
+
docker_dir.mkdir(parents=True, exist_ok=True)
|
|
528
|
+
|
|
529
|
+
# Dockerfile
|
|
530
|
+
dockerfile_template = self._load_template("docker/Dockerfile.template")
|
|
531
|
+
(docker_dir / "Dockerfile").write_text(
|
|
532
|
+
dockerfile_template.format(project_name=self.project_name),
|
|
533
|
+
encoding="utf-8"
|
|
534
|
+
)
|
|
535
|
+
|
|
536
|
+
# docker-compose.yml
|
|
537
|
+
docker_compose_template = self._load_template("docker/docker-compose.yml.template")
|
|
538
|
+
(docker_dir / "docker-compose.yml").write_text(
|
|
539
|
+
docker_compose_template.format(project_name=self.project_name),
|
|
540
|
+
encoding="utf-8"
|
|
541
|
+
)
|
|
542
|
+
|
|
543
|
+
# .dockerignore
|
|
544
|
+
dockerignore_template = self._load_template("docker/.dockerignore.template")
|
|
545
|
+
(docker_dir / ".dockerignore").write_text(
|
|
546
|
+
dockerignore_template.format(project_name=self.project_name),
|
|
547
|
+
encoding="utf-8"
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
# MySQL configuration
|
|
551
|
+
mysql_conf_dir = docker_dir / "mysql" / "conf.d"
|
|
552
|
+
mysql_conf_dir.mkdir(parents=True, exist_ok=True)
|
|
553
|
+
|
|
554
|
+
mysql_config_template = self._load_template("docker/mysql_custom.cnf.template")
|
|
555
|
+
(mysql_conf_dir / "custom.cnf").write_text(
|
|
556
|
+
mysql_config_template.format(project_name=self.project_name),
|
|
557
|
+
encoding="utf-8"
|
|
558
|
+
)
|
|
559
|
+
|
|
560
|
+
# MySQL init script
|
|
561
|
+
mysql_init_dir = docker_dir / "mysql" / "init"
|
|
562
|
+
mysql_init_dir.mkdir(parents=True, exist_ok=True)
|
|
563
|
+
|
|
564
|
+
mysql_init_template = self._load_template("docker/mysql_init.sql.template")
|
|
565
|
+
(mysql_init_dir / "01-init.sql").write_text(
|
|
566
|
+
mysql_init_template.format(project_name=self.project_name),
|
|
567
|
+
encoding="utf-8"
|
|
568
|
+
)
|
|
569
|
+
|
|
570
|
+
# README
|
|
571
|
+
readme_template = self._load_template("docker/README.md.template")
|
|
572
|
+
(docker_dir / "README.md").write_text(
|
|
573
|
+
readme_template.format(project_name=self.project_name),
|
|
574
|
+
encoding="utf-8"
|
|
575
|
+
)
|
|
576
|
+
|
|
577
|
+
print(f"✓ Docker files generated in '{self.project_name}/docker/' directory")
|
|
578
|
+
print(f"\n📦 Generated Docker files:")
|
|
579
|
+
print(f" • docker/Dockerfile")
|
|
580
|
+
print(f" • docker/docker-compose.yml")
|
|
581
|
+
print(f" • docker/.dockerignore")
|
|
582
|
+
print(f" • docker/mysql/conf.d/custom.cnf")
|
|
583
|
+
print(f" • docker/mysql/init/01-init.sql")
|
|
584
|
+
print(f" • docker/README.md")
|
|
585
|
+
print(f"\n🚀 Quick start:")
|
|
586
|
+
print(f" cd {self.project_name}/docker")
|
|
587
|
+
print(f" docker-compose up -d")
|
|
588
|
+
|
|
589
|
+
def generate(self) -> None:
|
|
590
|
+
"""生成完整的项目结构"""
|
|
591
|
+
if self.target_dir.exists():
|
|
592
|
+
raise FileExistsError(f"Directory '{self.target_dir}' already exists")
|
|
593
|
+
|
|
594
|
+
# 创建项目根目录
|
|
595
|
+
self.target_dir.mkdir(parents=True, exist_ok=True)
|
|
596
|
+
|
|
597
|
+
# 创建 app 目录结构
|
|
598
|
+
app_dir = self.target_dir / "app"
|
|
599
|
+
app_dir.mkdir(parents=True, exist_ok=True)
|
|
600
|
+
self.create_structure(self.STRUCTURE, app_dir)
|
|
601
|
+
|
|
602
|
+
# 创建 config 目录结构
|
|
603
|
+
config_dir = self.target_dir / "config"
|
|
604
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
|
605
|
+
self.create_structure(self.CONFIG_STRUCTURE, config_dir)
|
|
606
|
+
|
|
607
|
+
# 创建配置文件
|
|
608
|
+
self.create_config_files()
|
|
609
|
+
|
|
610
|
+
# 创建 Makefile
|
|
611
|
+
self.create_makefile()
|
|
612
|
+
|
|
613
|
+
# 创建 service.sh
|
|
614
|
+
self.create_service_script()
|
|
615
|
+
|
|
616
|
+
print(f"✓ Project '{self.project_name}' created successfully!")
|
|
617
|
+
print(f"\nGenerated structure:")
|
|
618
|
+
print(f" 📁 Application code (app/)")
|
|
619
|
+
print(f" 📁 Configuration (config/)")
|
|
620
|
+
print(f" 📄 Environment (.env)")
|
|
621
|
+
print(f" 🔧 Development tools (Makefile)")
|
|
622
|
+
print(f" 🚀 Service management (service.sh)")
|
|
623
|
+
print(f"\nNext steps:")
|
|
624
|
+
print(f" cd {self.project_name}")
|
|
625
|
+
print(f" make help # See all commands")
|
|
626
|
+
print(f"\n Quick start (local):")
|
|
627
|
+
print(f" make init-env && make install && make dev")
|
|
628
|
+
print(f"\n Quick start (Docker):")
|
|
629
|
+
print(f" make docker-build && make docker-up")
|
|
630
|
+
print(f"\n📚 Documentation:")
|
|
631
|
+
print(f" README.md - Project overview")
|
|
632
|
+
print(f" doc/1-API-GUIDE.md - API development guide")
|
|
633
|
+
print(f" doc/2-DEPLOYMENT.md - Deployment instructions")
|
|
634
|
+
print(f"\n🌐 After starting: http://localhost:8000/docs")
|