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/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
infoman/cli/README.md
ADDED
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
# Infoman CLI - 项目脚手架工具
|
|
2
|
+
|
|
3
|
+
快速生成基于 infomankit 标准架构的项目结构。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install infomankit
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 使用方法
|
|
12
|
+
|
|
13
|
+
### 1. 交互式创建项目
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
infomancli init
|
|
17
|
+
# 会提示输入项目名称
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### 2. 直接指定项目名称
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
infomancli init my-awesome-project
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 3. 指定目标目录
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# 在指定目录下创建项目
|
|
30
|
+
infomancli init my-project --dir /path/to/workspace
|
|
31
|
+
|
|
32
|
+
# 在临时目录测试
|
|
33
|
+
infomancli init test-project --dir /tmp
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 4. 查看帮助
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
infomancli --help
|
|
40
|
+
infomancli --version
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 生成的项目结构
|
|
44
|
+
|
|
45
|
+
生成的项目遵循 `infoman/service` 的标准架构:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
my-project/
|
|
49
|
+
├── .env.example # 环境变量模板
|
|
50
|
+
├── .gitignore # Git 忽略文件
|
|
51
|
+
├── README.md # 项目说明文档
|
|
52
|
+
├── main.py # 主应用入口
|
|
53
|
+
├── pyproject.toml # 项目配置文件
|
|
54
|
+
│
|
|
55
|
+
├── core/ # 核心业务逻辑
|
|
56
|
+
│ ├── __init__.py
|
|
57
|
+
│ ├── auth.py # 认证授权
|
|
58
|
+
│ └── response.py # 标准响应模型
|
|
59
|
+
│
|
|
60
|
+
├── routers/ # API 路由
|
|
61
|
+
│ └── __init__.py # API 路由注册
|
|
62
|
+
│
|
|
63
|
+
├── models/ # 数据模型
|
|
64
|
+
│ ├── __init__.py
|
|
65
|
+
│ ├── entity/ # 数据库实体 (ORM 模型)
|
|
66
|
+
│ ├── dto/ # 数据传输对象 (API 模型)
|
|
67
|
+
│ └── schemas/ # Pydantic 验证模式
|
|
68
|
+
│
|
|
69
|
+
├── repository/ # 数据访问层
|
|
70
|
+
│ └── __init__.py
|
|
71
|
+
│
|
|
72
|
+
├── services/ # 业务逻辑服务
|
|
73
|
+
│ └── __init__.py
|
|
74
|
+
│
|
|
75
|
+
├── exception/ # 自定义异常
|
|
76
|
+
│ └── __init__.py
|
|
77
|
+
│
|
|
78
|
+
├── middleware/ # 自定义中间件
|
|
79
|
+
│ └── __init__.py
|
|
80
|
+
│
|
|
81
|
+
├── infrastructure/ # 基础设施
|
|
82
|
+
│ ├── __init__.py
|
|
83
|
+
│ ├── database/ # 数据库连接
|
|
84
|
+
│ └── cache/ # 缓存管理
|
|
85
|
+
│
|
|
86
|
+
└── utils/ # 工具函数
|
|
87
|
+
├── __init__.py
|
|
88
|
+
├── cache/ # 缓存工具
|
|
89
|
+
└── parse/ # 解析工具
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## 项目初始化步骤
|
|
93
|
+
|
|
94
|
+
创建项目后,按照以下步骤进行初始化:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# 1. 进入项目目录
|
|
98
|
+
cd my-project
|
|
99
|
+
|
|
100
|
+
# 2. 安装依赖
|
|
101
|
+
pip install -e .
|
|
102
|
+
|
|
103
|
+
# 3. 复制环境变量文件
|
|
104
|
+
cp .env.example .env
|
|
105
|
+
|
|
106
|
+
# 4. 编辑 .env 配置你的环境变量
|
|
107
|
+
vim .env
|
|
108
|
+
|
|
109
|
+
# 5. 运行开发服务器
|
|
110
|
+
infoman-serve run main:app --reload
|
|
111
|
+
|
|
112
|
+
# 6. 访问 API 文档
|
|
113
|
+
open http://localhost:8000/docs
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## 架构说明
|
|
117
|
+
|
|
118
|
+
生成的项目遵循 infomankit 的标准架构,各目录职责如下:
|
|
119
|
+
|
|
120
|
+
### core/
|
|
121
|
+
核心业务逻辑和应用生命周期管理
|
|
122
|
+
- `auth.py` - 认证和授权逻辑
|
|
123
|
+
- `response.py` - 标准 API 响应模型
|
|
124
|
+
|
|
125
|
+
### routers/
|
|
126
|
+
API 端点和路由定义
|
|
127
|
+
- 所有的 API 路由在此定义
|
|
128
|
+
- 使用 FastAPI 的 `APIRouter`
|
|
129
|
+
|
|
130
|
+
### models/
|
|
131
|
+
数据模型定义
|
|
132
|
+
- `entity/` - 数据库 ORM 模型 (支持 Tortoise ORM 或 SQLAlchemy)
|
|
133
|
+
- `dto/` - API 请求/响应的数据传输对象
|
|
134
|
+
- `schemas/` - Pydantic 数据验证模式
|
|
135
|
+
|
|
136
|
+
### repository/
|
|
137
|
+
数据访问层 (Repository 模式)
|
|
138
|
+
- 封装数据库操作
|
|
139
|
+
- 提供数据访问接口
|
|
140
|
+
|
|
141
|
+
### services/
|
|
142
|
+
业务逻辑服务层
|
|
143
|
+
- 处理复杂的业务逻辑
|
|
144
|
+
- 协调多个 repository
|
|
145
|
+
|
|
146
|
+
### exception/
|
|
147
|
+
自定义异常
|
|
148
|
+
- 继承自 infomankit 的异常基类
|
|
149
|
+
- 统一的异常处理
|
|
150
|
+
|
|
151
|
+
### middleware/
|
|
152
|
+
自定义中间件
|
|
153
|
+
- 可以使用 infomankit 内置的中间件
|
|
154
|
+
- 或实现自定义中间件
|
|
155
|
+
|
|
156
|
+
### infrastructure/
|
|
157
|
+
基础设施组件
|
|
158
|
+
- `database/` - 数据库连接和管理
|
|
159
|
+
- `cache/` - 缓存管理
|
|
160
|
+
|
|
161
|
+
### utils/
|
|
162
|
+
通用工具函数
|
|
163
|
+
- `cache/` - 缓存装饰器和工具
|
|
164
|
+
- `parse/` - 数据解析工具
|
|
165
|
+
|
|
166
|
+
## 生成的核心文件说明
|
|
167
|
+
|
|
168
|
+
### main.py
|
|
169
|
+
包含 FastAPI 应用的入口点:
|
|
170
|
+
- 使用 `infoman.service.app.create_app` 创建应用
|
|
171
|
+
- 注册路由
|
|
172
|
+
- 提供基础的健康检查端点
|
|
173
|
+
|
|
174
|
+
### pyproject.toml
|
|
175
|
+
项目配置文件:
|
|
176
|
+
- 项目元数据
|
|
177
|
+
- 依赖声明 (默认包含 `infomankit[web]`)
|
|
178
|
+
- 开发依赖和工具配置
|
|
179
|
+
|
|
180
|
+
### .env.example
|
|
181
|
+
环境变量模板:
|
|
182
|
+
- 应用基础配置 (名称、端口、日志)
|
|
183
|
+
- 数据库配置 (MySQL, PostgreSQL)
|
|
184
|
+
- 缓存配置 (Redis)
|
|
185
|
+
- 向量数据库配置 (Qdrant)
|
|
186
|
+
- 消息队列配置 (NATS)
|
|
187
|
+
- LLM 配置
|
|
188
|
+
|
|
189
|
+
### README.md
|
|
190
|
+
项目说明文档:
|
|
191
|
+
- 项目介绍和快速开始
|
|
192
|
+
- 项目结构说明
|
|
193
|
+
- API 开发流程
|
|
194
|
+
- 使用示例
|
|
195
|
+
|
|
196
|
+
## 开发流程
|
|
197
|
+
|
|
198
|
+
### 1. 创建数据模型
|
|
199
|
+
|
|
200
|
+
在 `models/entity/` 创建 ORM 模型:
|
|
201
|
+
```python
|
|
202
|
+
from infoman.service.models.base import BaseModel
|
|
203
|
+
from sqlalchemy import Column, String, Integer
|
|
204
|
+
|
|
205
|
+
class User(BaseModel):
|
|
206
|
+
__tablename__ = "users"
|
|
207
|
+
|
|
208
|
+
id = Column(Integer, primary_key=True)
|
|
209
|
+
name = Column(String(100), nullable=False)
|
|
210
|
+
email = Column(String(100), unique=True)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### 2. 定义 DTO
|
|
214
|
+
|
|
215
|
+
在 `models/dto/` 创建 API 模型:
|
|
216
|
+
```python
|
|
217
|
+
from pydantic import BaseModel, EmailStr
|
|
218
|
+
|
|
219
|
+
class UserCreateDTO(BaseModel):
|
|
220
|
+
name: str
|
|
221
|
+
email: EmailStr
|
|
222
|
+
|
|
223
|
+
class UserResponseDTO(BaseModel):
|
|
224
|
+
id: int
|
|
225
|
+
name: str
|
|
226
|
+
email: str
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### 3. 实现 Repository
|
|
230
|
+
|
|
231
|
+
在 `repository/` 创建数据访问层:
|
|
232
|
+
```python
|
|
233
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
234
|
+
from sqlalchemy import select
|
|
235
|
+
from models.entity import User
|
|
236
|
+
|
|
237
|
+
class UserRepository:
|
|
238
|
+
def __init__(self, session: AsyncSession):
|
|
239
|
+
self.session = session
|
|
240
|
+
|
|
241
|
+
async def get_by_id(self, user_id: int) -> User | None:
|
|
242
|
+
result = await self.session.execute(
|
|
243
|
+
select(User).where(User.id == user_id)
|
|
244
|
+
)
|
|
245
|
+
return result.scalar_one_or_none()
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### 4. 创建 Service
|
|
249
|
+
|
|
250
|
+
在 `services/` 实现业务逻辑:
|
|
251
|
+
```python
|
|
252
|
+
from repository.user_repository import UserRepository
|
|
253
|
+
from models.dto import UserCreateDTO, UserResponseDTO
|
|
254
|
+
|
|
255
|
+
class UserService:
|
|
256
|
+
def __init__(self, repo: UserRepository):
|
|
257
|
+
self.repo = repo
|
|
258
|
+
|
|
259
|
+
async def create_user(self, data: UserCreateDTO) -> UserResponseDTO:
|
|
260
|
+
# 业务逻辑
|
|
261
|
+
user = await self.repo.create(data)
|
|
262
|
+
return UserResponseDTO.from_orm(user)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### 5. 添加 API 端点
|
|
266
|
+
|
|
267
|
+
在 `routers/` 创建路由:
|
|
268
|
+
```python
|
|
269
|
+
from fastapi import APIRouter, Depends
|
|
270
|
+
from models.dto import UserCreateDTO, UserResponseDTO
|
|
271
|
+
|
|
272
|
+
router = APIRouter(prefix="/users", tags=["Users"])
|
|
273
|
+
|
|
274
|
+
@router.post("/", response_model=UserResponseDTO)
|
|
275
|
+
async def create_user(data: UserCreateDTO):
|
|
276
|
+
# 处理逻辑
|
|
277
|
+
pass
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
在 `routers/__init__.py` 注册路由:
|
|
281
|
+
```python
|
|
282
|
+
from .user_router import router as user_router
|
|
283
|
+
api_router.include_router(user_router)
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## 扩展项目
|
|
287
|
+
|
|
288
|
+
根据需求安装额外的依赖:
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
# 添加数据库支持 (SQLAlchemy)
|
|
292
|
+
pip install "infomankit[database-alchemy]"
|
|
293
|
+
|
|
294
|
+
# 添加缓存支持
|
|
295
|
+
pip install "infomankit[cache]"
|
|
296
|
+
|
|
297
|
+
# 添加 LLM 支持
|
|
298
|
+
pip install "infomankit[llm]"
|
|
299
|
+
|
|
300
|
+
# 添加向量数据库支持
|
|
301
|
+
pip install "infomankit[vector]"
|
|
302
|
+
|
|
303
|
+
# 添加消息队列支持
|
|
304
|
+
pip install "infomankit[messaging]"
|
|
305
|
+
|
|
306
|
+
# 完整功能
|
|
307
|
+
pip install "infomankit[full]"
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
在 `pyproject.toml` 中更新依赖:
|
|
311
|
+
```toml
|
|
312
|
+
dependencies = [
|
|
313
|
+
"infomankit[web,database-alchemy,cache]>=0.3.0",
|
|
314
|
+
]
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## 最佳实践
|
|
318
|
+
|
|
319
|
+
### 目录使用指南
|
|
320
|
+
|
|
321
|
+
- **core/** - 核心业务逻辑,与技术实现无关
|
|
322
|
+
- **routers/** - API 端点定义,保持精简
|
|
323
|
+
- **models/entity/** - 数据库表结构
|
|
324
|
+
- **models/dto/** - API 输入/输出模型
|
|
325
|
+
- **repository/** - 数据库操作封装
|
|
326
|
+
- **services/** - 复杂业务逻辑编排
|
|
327
|
+
- **exception/** - 自定义异常和错误处理
|
|
328
|
+
- **middleware/** - 请求/响应拦截处理
|
|
329
|
+
- **infrastructure/** - 外部服务连接管理
|
|
330
|
+
- **utils/** - 可复用的工具函数
|
|
331
|
+
|
|
332
|
+
### 架构原则
|
|
333
|
+
|
|
334
|
+
1. **分层架构**: Router -> Service -> Repository -> Database
|
|
335
|
+
2. **依赖注入**: 使用 FastAPI 的依赖注入系统
|
|
336
|
+
3. **单一职责**: 每个模块只负责一件事
|
|
337
|
+
4. **异常处理**: 使用 infomankit 提供的异常类
|
|
338
|
+
5. **日志记录**: 使用 infomankit 的日志系统
|
|
339
|
+
6. **配置管理**: 使用环境变量和 Pydantic Settings
|
|
340
|
+
|
|
341
|
+
## 常见问题
|
|
342
|
+
|
|
343
|
+
### Q: 项目已存在怎么办?
|
|
344
|
+
A: CLI 会检查目录是否存在,如果存在会报错。请选择不同的项目名称或删除现有目录。
|
|
345
|
+
|
|
346
|
+
### Q: 如何选择 ORM?
|
|
347
|
+
A: 默认支持 SQLAlchemy 2.0。在 `.env` 中设置 `ORM_BACKEND=sqlalchemy` 或 `ORM_BACKEND=tortoise`。
|
|
348
|
+
|
|
349
|
+
### Q: 如何自定义项目结构?
|
|
350
|
+
A: 生成项目后,可以根据需要添加或删除目录。生成的结构是推荐的最佳实践。
|
|
351
|
+
|
|
352
|
+
### Q: 可以在现有项目中使用吗?
|
|
353
|
+
A: 建议用于新项目。如果要在现有项目中使用,可以生成到临时目录,然后手动复制需要的部分。
|
|
354
|
+
|
|
355
|
+
### Q: 与 infoman/service 有什么关系?
|
|
356
|
+
A: 生成的项目结构完全遵循 `infoman/service` 的标准架构,可以无缝使用 infomankit 的所有功能。
|
|
357
|
+
|
|
358
|
+
## 与 infomankit 的集成
|
|
359
|
+
|
|
360
|
+
生成的项目自动集成了以下 infomankit 功能:
|
|
361
|
+
|
|
362
|
+
- ✅ FastAPI 应用工厂 (`create_app`)
|
|
363
|
+
- ✅ 异步数据库支持 (Tortoise ORM / SQLAlchemy)
|
|
364
|
+
- ✅ Redis 缓存
|
|
365
|
+
- ✅ 日志系统
|
|
366
|
+
- ✅ 异常处理
|
|
367
|
+
- ✅ 中间件系统
|
|
368
|
+
- ✅ 配置管理
|
|
369
|
+
- ✅ 健康检查端点
|
|
370
|
+
|
|
371
|
+
## 反馈与贡献
|
|
372
|
+
|
|
373
|
+
- Issue: https://github.com/infoman-lib/infoman-pykit/issues
|
|
374
|
+
- PR: https://github.com/infoman-lib/infoman-pykit/pulls
|
|
375
|
+
|
|
376
|
+
## 许可证
|
|
377
|
+
|
|
378
|
+
MIT License
|
infoman/cli/__init__.py
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Init command - Create a new project structure and generate development files
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Optional, Literal
|
|
8
|
+
|
|
9
|
+
from infoman.cli.scaffold import ProjectScaffold
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def init_project(project_name: Optional[str] = None, target_dir: Optional[str] = None) -> int:
|
|
13
|
+
"""
|
|
14
|
+
Initialize a new project with standard structure
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
project_name: Name of the project (optional, will prompt if not provided)
|
|
18
|
+
target_dir: Target directory (optional, defaults to current directory)
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
Exit code (0 for success, 1 for error)
|
|
22
|
+
"""
|
|
23
|
+
# Get project name from argument or prompt
|
|
24
|
+
if not project_name:
|
|
25
|
+
try:
|
|
26
|
+
project_name = input("Enter project name: ").strip()
|
|
27
|
+
except (KeyboardInterrupt, EOFError):
|
|
28
|
+
print("\nOperation cancelled.")
|
|
29
|
+
return 1
|
|
30
|
+
|
|
31
|
+
if not project_name:
|
|
32
|
+
print("Error: Project name cannot be empty")
|
|
33
|
+
return 1
|
|
34
|
+
|
|
35
|
+
# Validate project name
|
|
36
|
+
if not project_name.replace("-", "").replace("_", "").isalnum():
|
|
37
|
+
print("Error: Project name can only contain letters, numbers, hyphens, and underscores")
|
|
38
|
+
return 1
|
|
39
|
+
|
|
40
|
+
# Parse target directory
|
|
41
|
+
target_path = Path(target_dir) / project_name if target_dir else None
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
# Create scaffold generator
|
|
45
|
+
scaffold = ProjectScaffold(project_name, target_path)
|
|
46
|
+
|
|
47
|
+
# Generate project structure
|
|
48
|
+
scaffold.generate()
|
|
49
|
+
|
|
50
|
+
return 0
|
|
51
|
+
|
|
52
|
+
except FileExistsError as e:
|
|
53
|
+
print(f"Error: {e}")
|
|
54
|
+
print("Please choose a different project name or remove the existing directory.")
|
|
55
|
+
return 1
|
|
56
|
+
|
|
57
|
+
except PermissionError as e:
|
|
58
|
+
print(f"Error: Permission denied - {e}")
|
|
59
|
+
return 1
|
|
60
|
+
|
|
61
|
+
except Exception as e:
|
|
62
|
+
print(f"Error: Failed to create project - {e}")
|
|
63
|
+
return 1
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def generate_module(
|
|
67
|
+
module_name: str,
|
|
68
|
+
scaffold_type: Literal["basic", "full"] = "basic",
|
|
69
|
+
target_dir: Optional[str] = None
|
|
70
|
+
) -> int:
|
|
71
|
+
"""
|
|
72
|
+
Generate new module in existing project
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
module_name: Module name (e.g., 'investor', 'contract')
|
|
76
|
+
scaffold_type: 'basic' or 'full'
|
|
77
|
+
target_dir: Target directory (default: ./app)
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Exit code (0 for success, 1 for error)
|
|
81
|
+
"""
|
|
82
|
+
# Import here to avoid circular dependency
|
|
83
|
+
try:
|
|
84
|
+
# Try to import from command first (temporary during migration)
|
|
85
|
+
import sys
|
|
86
|
+
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
|
|
87
|
+
from command.scaffold import RWAModuleScaffold as ModuleScaffold
|
|
88
|
+
except ImportError:
|
|
89
|
+
try:
|
|
90
|
+
from infoman.cli.module_scaffold import ModuleScaffold
|
|
91
|
+
except ImportError:
|
|
92
|
+
print("Error: Module scaffold not found")
|
|
93
|
+
return 1
|
|
94
|
+
|
|
95
|
+
try:
|
|
96
|
+
target_path = Path(target_dir) if target_dir else Path.cwd() / "app"
|
|
97
|
+
|
|
98
|
+
scaffold = ModuleScaffold(
|
|
99
|
+
module_name=module_name,
|
|
100
|
+
scaffold_type=scaffold_type,
|
|
101
|
+
target_dir=target_path,
|
|
102
|
+
)
|
|
103
|
+
scaffold.generate()
|
|
104
|
+
return 0
|
|
105
|
+
except FileNotFoundError as e:
|
|
106
|
+
print(f"Error: {e}")
|
|
107
|
+
print("Make sure you're in a project directory with an 'app' folder")
|
|
108
|
+
return 1
|
|
109
|
+
except Exception as e:
|
|
110
|
+
print(f"Error: Failed to generate module - {e}")
|
|
111
|
+
import traceback
|
|
112
|
+
traceback.print_exc()
|
|
113
|
+
return 1
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def generate_makefile(project_name: Optional[str] = None, force: bool = False) -> int:
|
|
117
|
+
"""
|
|
118
|
+
Generate Makefile for existing project
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
project_name: Project name (optional, defaults to current directory name)
|
|
122
|
+
force: Overwrite existing Makefile
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Exit code (0 for success, 1 for error)
|
|
126
|
+
"""
|
|
127
|
+
import os
|
|
128
|
+
|
|
129
|
+
# Get project name
|
|
130
|
+
if not project_name:
|
|
131
|
+
project_name = Path.cwd().name
|
|
132
|
+
|
|
133
|
+
# Check if Makefile exists
|
|
134
|
+
makefile_path = Path.cwd() / "Makefile"
|
|
135
|
+
if makefile_path.exists() and not force:
|
|
136
|
+
print(f"Error: Makefile already exists")
|
|
137
|
+
print(f"Use --force to overwrite")
|
|
138
|
+
return 1
|
|
139
|
+
|
|
140
|
+
# Read template
|
|
141
|
+
template_path = Path(__file__).parent.parent / "templates" / "Makefile.template"
|
|
142
|
+
try:
|
|
143
|
+
template_content = template_path.read_text(encoding="utf-8")
|
|
144
|
+
except FileNotFoundError:
|
|
145
|
+
print(f"Error: Template not found at {template_path}")
|
|
146
|
+
return 1
|
|
147
|
+
|
|
148
|
+
# Replace placeholder
|
|
149
|
+
makefile_content = template_content.replace("{{PROJECT_NAME}}", project_name)
|
|
150
|
+
|
|
151
|
+
# Write Makefile
|
|
152
|
+
try:
|
|
153
|
+
makefile_path.write_text(makefile_content, encoding="utf-8")
|
|
154
|
+
print(f"✓ Makefile created successfully!")
|
|
155
|
+
print(f"\nProject: {project_name}")
|
|
156
|
+
print(f"\nRun 'make help' to see available commands.")
|
|
157
|
+
return 0
|
|
158
|
+
except Exception as e:
|
|
159
|
+
print(f"Error: Failed to create Makefile - {e}")
|
|
160
|
+
return 1
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def generate_docker(project_name: Optional[str] = None) -> int:
|
|
164
|
+
"""
|
|
165
|
+
Generate Docker configuration files for existing project
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
project_name: Project name (optional, defaults to current directory name)
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
Exit code (0 for success, 1 for error)
|
|
172
|
+
"""
|
|
173
|
+
# Get project name
|
|
174
|
+
if not project_name:
|
|
175
|
+
project_name = Path.cwd().name
|
|
176
|
+
|
|
177
|
+
try:
|
|
178
|
+
# Create scaffold with current directory
|
|
179
|
+
scaffold = ProjectScaffold(project_name, Path.cwd())
|
|
180
|
+
|
|
181
|
+
# Generate Docker files
|
|
182
|
+
scaffold.generate_docker_files()
|
|
183
|
+
|
|
184
|
+
return 0
|
|
185
|
+
except Exception as e:
|
|
186
|
+
print(f"Error: Failed to generate Docker files - {e}")
|
|
187
|
+
import traceback
|
|
188
|
+
traceback.print_exc()
|
|
189
|
+
return 1
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def main() -> None:
|
|
193
|
+
"""Main entry point for CLI"""
|
|
194
|
+
import argparse
|
|
195
|
+
|
|
196
|
+
parser = argparse.ArgumentParser(
|
|
197
|
+
description="Infoman CLI - Project scaffolding and development tools",
|
|
198
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
199
|
+
epilog="""
|
|
200
|
+
Commands:
|
|
201
|
+
init Create a new project with full structure
|
|
202
|
+
makefile Generate Makefile for existing project
|
|
203
|
+
module Generate new module in existing project
|
|
204
|
+
docker Generate Docker configuration files
|
|
205
|
+
|
|
206
|
+
Examples:
|
|
207
|
+
# Project initialization
|
|
208
|
+
infomankit init # Interactive mode
|
|
209
|
+
infomankit init my-project # Create project named 'my-project'
|
|
210
|
+
infomankit init my-app --dir /tmp # Create in specific directory
|
|
211
|
+
|
|
212
|
+
# Makefile generation
|
|
213
|
+
infomankit makefile # Generate Makefile in current directory
|
|
214
|
+
infomankit makefile --force # Overwrite existing Makefile
|
|
215
|
+
infomankit makefile --name my-app # Set project name
|
|
216
|
+
|
|
217
|
+
# Module generation
|
|
218
|
+
infomankit module investor # Generate basic module
|
|
219
|
+
infomankit module token --type full # Generate full module (with utils & tests)
|
|
220
|
+
infomankit module contract --target /path/to/app # Custom target directory
|
|
221
|
+
|
|
222
|
+
# Docker generation
|
|
223
|
+
infomankit docker # Generate Docker files in current project
|
|
224
|
+
infomankit docker --name my-app # Specify project name
|
|
225
|
+
|
|
226
|
+
For more information, visit: https://github.com/infoman-lib/infoman-pykit
|
|
227
|
+
""",
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
parser.add_argument(
|
|
231
|
+
"command",
|
|
232
|
+
choices=["init", "makefile", "module", "docker"],
|
|
233
|
+
help="Command to execute",
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
parser.add_argument(
|
|
237
|
+
"project_name",
|
|
238
|
+
nargs="?",
|
|
239
|
+
help="Name of the project (for init command)",
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
parser.add_argument(
|
|
243
|
+
"--dir",
|
|
244
|
+
"-d",
|
|
245
|
+
dest="target_dir",
|
|
246
|
+
help="Target directory (for init command, default: current directory)",
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
parser.add_argument(
|
|
250
|
+
"--name",
|
|
251
|
+
"-n",
|
|
252
|
+
dest="makefile_name",
|
|
253
|
+
help="Project name (for makefile command, default: current directory name)",
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
parser.add_argument(
|
|
257
|
+
"--type",
|
|
258
|
+
"-t",
|
|
259
|
+
dest="module_type",
|
|
260
|
+
choices=["basic", "full"],
|
|
261
|
+
default="basic",
|
|
262
|
+
help="Module scaffold type (for module command): basic or full",
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
parser.add_argument(
|
|
266
|
+
"--target",
|
|
267
|
+
dest="module_target",
|
|
268
|
+
help="Target directory for module (default: ./app)",
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
parser.add_argument(
|
|
272
|
+
"--force",
|
|
273
|
+
"-f",
|
|
274
|
+
action="store_true",
|
|
275
|
+
help="Force overwrite existing files (for makefile command)",
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
parser.add_argument(
|
|
279
|
+
"--version",
|
|
280
|
+
"-V",
|
|
281
|
+
action="version",
|
|
282
|
+
version="infomankit 0.3.15",
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
args = parser.parse_args()
|
|
286
|
+
|
|
287
|
+
if args.command == "init":
|
|
288
|
+
exit_code = init_project(args.project_name, args.target_dir)
|
|
289
|
+
sys.exit(exit_code)
|
|
290
|
+
elif args.command == "makefile":
|
|
291
|
+
exit_code = generate_makefile(args.makefile_name, args.force)
|
|
292
|
+
sys.exit(exit_code)
|
|
293
|
+
elif args.command == "module":
|
|
294
|
+
if not args.project_name:
|
|
295
|
+
print("Error: Module name is required")
|
|
296
|
+
print("Usage: infomankit module <module_name> [--type basic|full] [--target DIR]")
|
|
297
|
+
sys.exit(1)
|
|
298
|
+
exit_code = generate_module(
|
|
299
|
+
module_name=args.project_name,
|
|
300
|
+
scaffold_type=args.module_type,
|
|
301
|
+
target_dir=args.module_target
|
|
302
|
+
)
|
|
303
|
+
sys.exit(exit_code)
|
|
304
|
+
elif args.command == "docker":
|
|
305
|
+
# For docker command, project_name is optional (uses --name flag or current dir)
|
|
306
|
+
project_name = args.makefile_name or args.project_name
|
|
307
|
+
exit_code = generate_docker(project_name)
|
|
308
|
+
sys.exit(exit_code)
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
if __name__ == "__main__":
|
|
312
|
+
main()
|