Metadata-Version: 2.4
Name: wr-common-lib
Version: 0.1.0
Summary: 气象导航公用库：领域枚举与共享数据访问
License: MIT
License-File: LICENSE
Requires-Python: >=3.12
Provides-Extra: db
Requires-Dist: async-db-tools>=0.1.0; extra == 'db'
Description-Content-Type: text/markdown

# wr-common-lib

气象导航各微服务共用的 Python 库：领域枚举、任务类型、以及已定表的共享数据访问（`EmailDbOper` 等）。

| 概念 | 名称 |
|------|------|
| PyPI / pip 包名 | `wr-common-lib` |
| import 包名 | `wr_common_lib` |
| 本仓库目录 | `common-lib/` |

要求 **Python ≥ 3.12**。

## 目录结构

```
common-lib/
├── LICENSE
├── pyproject.toml
├── README.md
└── src/wr_common_lib/
    ├── __init__.py          # __version__
    └── email/               # email 表相关
        ├── constants.py     # MailFlow, MailStatus（对齐 PG 枚举）
        ├── types.py         # OutboundTask, InboundTask
        └── db_oper.py       # EmailDbOper（需 [db] 可选依赖）
```

后续新业务域可在 `wr_common_lib/` 下增加子包（例如 `voyage/`），与 `email/` 平级。

## 安装

### 仅枚举 / 类型（无数据库依赖）

```bash
pip install wr-common-lib
# 或 monorepo 本地
pip install -e /path/to/common-lib
```

### 含 `EmailDbOper`（依赖 async-db-tools）

```bash
pip install "wr-common-lib[db]"
```

### monorepo 本地联调（推荐）

在 `publish` 仓库内，先装数据库工具包，再装本库：

```bash
pip install -e ../dbtools
pip install -e ".[db]"
```

若业务项目的 `pyproject.toml` 使用 path 依赖，示例：

```toml
dependencies = [
    "wr-common-lib[db] @ file:///${PROJECT_ROOT}/../common-lib",
    "async-db-tools @ file:///${PROJECT_ROOT}/../dbtools",
]
```

（路径按你本机 monorepo 布局调整；也可用 `uv` / `poetry` 的 path / workspace 写法。）

## 使用

### 邮件枚举

与 PostgreSQL `mail_flow`、`mail_status` 枚举值一致，可直接 `.value` 写入 SQL 或 ORM。

```python
from wr_common_lib.email import MailFlow, MailStatus

MailFlow.OUTBOUND          # "OUTBOUND"
MailStatus.QUEUED.value      # "QUEUED"

if MailStatus.SENT.is_terminal:
    ...
if MailStatus.PENDING.is_outbound_lifecycle:
    ...
```

### 任务类型（TypedDict）

出站、入站字段名不同，用类型区分，避免 `dict` 混用 `to` / `mail_to`：

```python
from wr_common_lib.email import OutboundTask, InboundTask

task: OutboundTask = {
    "imo": 1234567,
    "voyage_id": "...",
    "mail_from": "noreply@example.com",
    "to": "ship@example.com",
    "content_hash": "abc...",
}
```

### 共享表操作 `EmailDbOper`

需已安装 `[db]`，并注入各服务自己的 `PostgresPool`：

```python
from async_db_tools import PostgresPool
from wr_common_lib.email import EmailDbOper, MailStatus

db_oper = EmailDbOper(pool)

email_id = await db_oper.mark_queued(task)
await db_oper.mark_sent(email_id)
await db_oper.mark_failed(email_id)

row = await db_oper.find_by_content_hash("...")
email_id = await db_oper.insert_inbound_received(inbound_task, content_hash)
await db_oper.mark_parsed(email_id, {"key": "value"})
```

`EmailDbOper` 在 `wr_common_lib.email` 中为**懒加载**：只 `import MailStatus` 时不会要求安装 `async-db-tools`；只有 `import EmailDbOper` 时才加载 `db_oper` 模块。

### 邮件状态（约定）

```
出站 · 发送服务:  PENDING → QUEUED → SENT | FAILED
出站 · Webhook:   SENT → DELIVERED | BOUNCED | DEFERRED
入站 · 收件服务:  RECEIVED → PARSED | PARSE_FAILED
```

## 依赖说明

| 安装方式 | 引入的依赖 |
|----------|------------|
| `wr-common-lib` | 无 |
| `wr-common-lib[db]` | `async-db-tools`（PostgreSQL 连接池） |

业务服务仍需自行配置数据库连接；本库只封装对 `email` 表的 SQL。

## 开发与发布

```bash
# 可编辑安装（monorepo 内先装 dbtools）
uv pip install -e ../dbtools
uv pip install -e ".[db]"

# 发版前改版本（可选）
uv version 0.1.1

# 构建并发布到 PyPI（推荐）
export UV_PUBLISH_TOKEN=pypi-xxxxxxxx   # PyPI → Account → API tokens
uv build
uv publish

# 或一步：构建产物在 dist/ 后上传
# uv build && uv publish
```

`uv publish` 会读取 `dist/` 里的 wheel/sdist 并上传；失败重试同一命令即可（PyPI 会忽略已存在的相同文件）。

也可用传统方式：`python -m build` + `twine upload dist/*`。

表结构变更时，在 `src/wr_common_lib/email/db_oper.py` 中扩展方法即可；各服务将 `app.email.*` 的引用改为 `wr_common_lib.email` 后统一升级版本。

## 版本

当前版本见 `wr_common_lib.__version__` 与 `pyproject.toml` 中的 `[project].version`。

## 许可证

MIT，见 [LICENSE](LICENSE)。
