create-dwy 0.25.3 → 0.26.0
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.
- package/CHANGELOG.md +10 -0
- package/package.json +1 -1
- package/templates/ai-tools/CHANGELOG.md +10 -0
- package/templates/ai-tools/VERSION +1 -1
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-commercial-sdk/SKILL.md +20 -0
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-github-action-publish/SKILL.md +1 -1
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/SKILL.md +6 -2
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/android.md +2 -2
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/backend-deploy.md +1 -1
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/frontend-deploy.md +1 -1
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/generic-release.md +2 -2
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/harmony.md +2 -2
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/ios.md +2 -2
- package/templates/ai-tools/skills//351/200/232/347/224/250/dwy-dependency-choice/SKILL.md +2 -2
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-sdk-spec/SKILL.md +0 -244
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-sdk-spec/assets/files-whitelist-snippet.json +0 -22
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-sdk-spec/assets/js-commercial.npmignore +0 -76
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-sdk-spec/assets/python-commercial-MANIFEST.in +0 -37
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-sdk-spec/assets/python-commercial.gitignore +0 -62
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-sdk-spec/references/js-commercial-guide.md +0 -133
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-sdk-spec/references/publish-blacklist.md +0 -106
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-sdk-spec/references/python-commercial-guide.md +0 -147
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-sdk-spec/references/sensitive-patterns.md +0 -112
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-sdk-spec/scripts/check_comments.py +0 -260
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-sdk-spec/scripts/check_js_publish.sh +0 -110
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-sdk-spec/scripts/check_python_publish.sh +0 -171
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-sdk-spec/scripts/detect_sdk.sh +0 -71
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-sdk-spec/scripts/init_config.sh +0 -91
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-semver/SKILL.md +0 -136
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-semver/references/semver-spec.md +0 -70
- package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-semver/scripts/bump.py +0 -137
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
# JS/TS 商业版 SDK 完整打包指南
|
|
2
|
-
|
|
3
|
-
目标:发布到 npm 的 `.tgz` 内**不含 src/、不含 sourcemap、不含 tsconfig**,只含压缩后的 `dist/` 与 `.d.ts` 类型定义。
|
|
4
|
-
|
|
5
|
-
## 关键原则
|
|
6
|
-
|
|
7
|
-
- `package.json` 的 `files` 字段是**白名单**,优先级高于 `.npmignore`
|
|
8
|
-
- 用 `tsup` 或 `rollup` 打包,强制 `minify: true` + `sourcemap: false` + `legalComments: 'none'`
|
|
9
|
-
- `.d.ts` 单独生成(用户要类型提示),但不能带 `.d.ts.map`(会映射回源码)
|
|
10
|
-
|
|
11
|
-
## 工具选择
|
|
12
|
-
|
|
13
|
-
| 工具 | 优势 | 推荐场景 |
|
|
14
|
-
|---|---|---|
|
|
15
|
-
| **tsup** | 零配置、内置 dts + 多格式 | **默认选择** |
|
|
16
|
-
| rollup + rollup-plugin-dts | 配置灵活、生态成熟 | 复杂 bundle 拆分 |
|
|
17
|
-
| esbuild | 最快、最小 | 简单单文件 SDK |
|
|
18
|
-
|
|
19
|
-
下面以 tsup 为准。
|
|
20
|
-
|
|
21
|
-
## 项目结构示例
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
mysdk/
|
|
25
|
-
├── package.json
|
|
26
|
-
├── tsup.config.ts
|
|
27
|
-
├── tsconfig.json # 仅本地用,不发
|
|
28
|
-
├── .gitignore
|
|
29
|
-
├── .npmignore # 可选(files 优先)
|
|
30
|
-
├── src/
|
|
31
|
-
│ ├── index.ts # 入口
|
|
32
|
-
│ ├── client.ts # 公开 API
|
|
33
|
-
│ └── _internal/ # 内部模块
|
|
34
|
-
│ └── engine.ts
|
|
35
|
-
└── dist/ # 构建产物(唯一发布内容)
|
|
36
|
-
├── index.js # ESM,minified
|
|
37
|
-
├── index.cjs # CJS,minified
|
|
38
|
-
└── index.d.ts # 类型定义(无 .map)
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## tsup.config.ts
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
import { defineConfig } from 'tsup'
|
|
45
|
-
|
|
46
|
-
export default defineConfig({
|
|
47
|
-
entry: ['src/index.ts'],
|
|
48
|
-
format: ['esm', 'cjs'],
|
|
49
|
-
dts: true, // 生成 .d.ts
|
|
50
|
-
sourcemap: false, // 关键:不生成 .map(防止源码可还原)
|
|
51
|
-
minify: true, // 压缩
|
|
52
|
-
legalComments: 'none', // 去掉 /*! */ 版权注释(可能含路径)
|
|
53
|
-
splitting: false, // 不拆分(防止内部模块结构暴露)
|
|
54
|
-
clean: true, // 构建前清 dist/
|
|
55
|
-
treeshake: true,
|
|
56
|
-
})
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## package.json
|
|
60
|
-
|
|
61
|
-
```json
|
|
62
|
-
{
|
|
63
|
-
"name": "@dwydev/mysdk",
|
|
64
|
-
"version": "1.0.0",
|
|
65
|
-
"main": "./dist/index.cjs",
|
|
66
|
-
"module": "./dist/index.js",
|
|
67
|
-
"types": "./dist/index.d.ts",
|
|
68
|
-
"exports": {
|
|
69
|
-
".": {
|
|
70
|
-
"import": "./dist/index.js",
|
|
71
|
-
"require": "./dist/index.cjs",
|
|
72
|
-
"types": "./dist/index.d.ts"
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
"files": [
|
|
76
|
-
"dist",
|
|
77
|
-
"README.md",
|
|
78
|
-
"LICENSE"
|
|
79
|
-
],
|
|
80
|
-
"scripts": {
|
|
81
|
-
"build": "tsup",
|
|
82
|
-
"prepublishOnly": "pnpm build && npm pack --dry-run"
|
|
83
|
-
},
|
|
84
|
-
"publishConfig": {
|
|
85
|
-
"registry": "https://registry.npmjs.org/",
|
|
86
|
-
"access": "public"
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
`files` 白名单只列 3 项 → 其他全部不发(src/、tests/、tsconfig.json、tsup.config.ts、node_modules/ 自动不发)。
|
|
92
|
-
|
|
93
|
-
## 构建命令
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
# 清理 + 打包
|
|
97
|
-
rm -rf dist/
|
|
98
|
-
pnpm build
|
|
99
|
-
|
|
100
|
-
# 验证 dist/ 无 .map
|
|
101
|
-
find dist -name '*.map' -type f && echo "FAIL: sourcemap leaked" || echo "OK: no sourcemap"
|
|
102
|
-
|
|
103
|
-
# 干跑看 .tgz 内容
|
|
104
|
-
npm pack --dry-run --json | jq '.[] | .files[] | .path'
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
## 验收清单(流程 B 用)
|
|
108
|
-
|
|
109
|
-
| 检查项 | 命令 |
|
|
110
|
-
|---|---|
|
|
111
|
-
| package.json 有 files 白名单 | `jq '.files \| length > 0' package.json` |
|
|
112
|
-
| files 不含 src/ | `jq '.files \| any(. == "src" or . == "src/")' package.json` 应为 false |
|
|
113
|
-
| tsup 配置 minify + 无 sourcemap | `grep -E 'minify.*true' tsup.config.*` + `grep -E 'sourcemap.*false' tsup.config.*` |
|
|
114
|
-
| dist/ 下无 .map | `find dist -name '*.map'` 应为空 |
|
|
115
|
-
| .gitignore 含 .env / *.tsbuildinfo | `grep -E '\.env\\|\.tsbuildinfo' .gitignore` |
|
|
116
|
-
|
|
117
|
-
## 常见踩坑
|
|
118
|
-
|
|
119
|
-
| 现象 | 原因 | 修复 |
|
|
120
|
-
|---|---|---|
|
|
121
|
-
| 用 `.npmignore` 但 files 也定义了 | `files` 优先,`.npmignore` 被忽略 | 二选一,推荐只用 `files` |
|
|
122
|
-
| `.tgz` 里有 `.DS_Store` | macOS 系统文件,没被 ignore | `.gitignore` 加 `.DS_Store`;npm 默认会带 .gitignore 规则 |
|
|
123
|
-
| 发布后 .d.ts 含内部路径 | tsup 生成的 .d.ts 没合并 | 用 `dts: { resolve: true }` 合并所有类型,或改用 rollup-plugin-dts |
|
|
124
|
-
| 装完后用户 IDE 跳转到 minified 代码 | `.d.ts.map` 不小心发了 | 检查 `dist/` 无 `.d.ts.map`,tsup 默认不生成 |
|
|
125
|
-
| `bin` 字段指向的 CLI 被压缩后报 "no entry" | 缺 shebang `#!/usr/bin/env node` | tsup 配 `banner: { js: '#!/usr/bin/env node' }` |
|
|
126
|
-
|
|
127
|
-
## 参考 dwy-shared 内已有 SDK
|
|
128
|
-
|
|
129
|
-
`frontend/eui/` / `frontend/ekit/` 当前是**开源版**(Vite 构建,含 `vite-plugin-dts`)。若要转商业版:
|
|
130
|
-
1. 把 Vite 换成 tsup(或在 Vite 配置加 `build.minify: 'terser'` + `build.sourcemap: false`)
|
|
131
|
-
2. `package.json` 添加 `files: ["dist", "README.md", "LICENSE"]`
|
|
132
|
-
3. 删除 `dist/` 下所有 `.map` 文件
|
|
133
|
-
4. 跑 `npm pack --dry-run` 验收
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
# PyPI / npm 发布黑名单
|
|
2
|
-
|
|
3
|
-
`check_python_publish.sh` / `check_js_publish.sh` 的规则源。
|
|
4
|
-
|
|
5
|
-
## Python(PyPI)
|
|
6
|
-
|
|
7
|
-
### 商业版:白名单(其他一律违规)
|
|
8
|
-
|
|
9
|
-
| 允许的文件 / 模式 | 说明 |
|
|
10
|
-
|---|---|
|
|
11
|
-
| `*.so` | 编译产物 |
|
|
12
|
-
| `*.pyi` | 类型存根(无源) |
|
|
13
|
-
| `py.typed` | 标记包支持类型检查 |
|
|
14
|
-
| `*.dist-info/**` | wheel 元数据(METADATA / RECORD / WHEEL / entry_points.txt 等) |
|
|
15
|
-
| `LICENSE` `LICENSE.*` `LICENCE` | 许可证(可在包外) |
|
|
16
|
-
| `README` `README.*` | 仅 dist-info 内 |
|
|
17
|
-
| `<pkg>/__init__.py` | 公开入口(如果用了 re-export 模式) |
|
|
18
|
-
| `<pkg>/<public_module>.py` | 不以 `_` 开头的公开 API 模块 |
|
|
19
|
-
| 业务必要资源(图片、json、模板) | 列入 `package-data` |
|
|
20
|
-
|
|
21
|
-
### 开源版:黑名单(任意命中视为违规)
|
|
22
|
-
|
|
23
|
-
| 禁止的文件 / 模式 | 原因 |
|
|
24
|
-
|---|---|
|
|
25
|
-
| `__pycache__/**` | 字节码缓存,可反编译 |
|
|
26
|
-
| `*.pyc` `*.pyo` | 同上 |
|
|
27
|
-
| `*.egg-info/**` | 旧式构建元数据,含本地路径 |
|
|
28
|
-
| `.mypy_cache/**` `.pytest_cache/**` `.ruff_cache/**` | 开发工具缓存 |
|
|
29
|
-
| `.pdb` `.idb` | 调试符号 |
|
|
30
|
-
| `.env` `.env.*` `.env.local` | 环境变量(凭证) |
|
|
31
|
-
| `.pypirc` | PyPI 凭证(致命) |
|
|
32
|
-
| `.git/**` `.gitignore` | 版本控制(含历史) |
|
|
33
|
-
| `.DS_Store` `Thumbs.db` | 系统文件 |
|
|
34
|
-
| `.vscode/**` `.idea/**` | IDE 配置(可能含路径) |
|
|
35
|
-
| `*.bak` `*.swp` `*.swo` `*~` | 编辑器临时文件 |
|
|
36
|
-
|
|
37
|
-
## npm
|
|
38
|
-
|
|
39
|
-
### 商业版:白名单(其他一律违规)
|
|
40
|
-
|
|
41
|
-
| 允许的文件 / 模式 | 说明 |
|
|
42
|
-
|---|---|
|
|
43
|
-
| `dist/**` | 构建产物(minified) |
|
|
44
|
-
| `package.json` | 必有 |
|
|
45
|
-
| `README` `README.*` | 用户必读 |
|
|
46
|
-
| `LICENSE` `LICENSE.*` `LICENCE` | 许可证 |
|
|
47
|
-
| `CHANGELOG` `CHANGELOG.*` | 可选 |
|
|
48
|
-
| `bin/**` | 仅 CLI 包 |
|
|
49
|
-
| `*.d.ts` 在 dist/ 内 | 类型定义 |
|
|
50
|
-
|
|
51
|
-
### 开源版:黑名单(任意命中视为违规)
|
|
52
|
-
|
|
53
|
-
| 禁止的文件 / 模式 | 原因 |
|
|
54
|
-
|---|---|
|
|
55
|
-
| `src/**` `tests/**` `__tests__/**` | 源码 / 测试(占体积) |
|
|
56
|
-
| `*.test.ts` `*.spec.ts` `*.test.js` `*.spec.js` | 测试文件 |
|
|
57
|
-
| `*.map` `*.js.map` `*.d.ts.map` | sourcemap(源码可还原) |
|
|
58
|
-
| `*.tsbuildinfo` | TS 增量编译信息(含路径) |
|
|
59
|
-
| `tsconfig*.json` | 编译配置 |
|
|
60
|
-
| `vite.config.*` `vitest.config.*` `tsup.config.*` `rollup.config.*` `webpack.config.*` | 打包配置 |
|
|
61
|
-
| `.eslintrc*` `.prettierrc*` `eslint.config.*` `prettier.config.*` | Lint 配置 |
|
|
62
|
-
| `.env` `.env.*` | 环境变量(凭证) |
|
|
63
|
-
| `.npmrc` `.yarnrc` `.pnpmrc` | 包管理器配置(含 token) |
|
|
64
|
-
| `.git/**` `.gitignore` `.gitattributes` | 版本控制 |
|
|
65
|
-
| `.github/**` `.gitlab-ci.yml` `.travis.yml` `.circleci/**` | CI 配置(含 secret 引用) |
|
|
66
|
-
| `.vscode/**` `.idea/**` `*.swp` | IDE / 编辑器 |
|
|
67
|
-
| `.DS_Store` `Thumbs.db` | 系统文件 |
|
|
68
|
-
| `node_modules/**` | 依赖(npm 自动忽略,但 .npmignore 错误时可能漏出) |
|
|
69
|
-
| `pnpm-lock.yaml` `package-lock.json` `yarn.lock` | 锁文件(npm 默认忽略) |
|
|
70
|
-
| `.husky/**` `commitlint.config.*` | Git hook 配置 |
|
|
71
|
-
|
|
72
|
-
## 致命级(任何版本都禁)
|
|
73
|
-
|
|
74
|
-
无论商业 / 开源,下列文件一旦发到 PyPI / npm 都视为**严重事故**,必须立即 `npm unpublish` / 联系 PyPI 删除:
|
|
75
|
-
|
|
76
|
-
| 文件 | 风险 |
|
|
77
|
-
|---|---|
|
|
78
|
-
| `.env*` | 含 API key / DB 密码 / 第三方凭证 |
|
|
79
|
-
| `.npmrc` `.pypirc` `.git-credentials` | 仓库 / 包管理器登录凭证 |
|
|
80
|
-
| `id_rsa` `id_ed25519` `*.pem` `*.key` `*.p12` | SSH / TLS 私钥 |
|
|
81
|
-
| `secrets.json` `credentials.json` `.aws/credentials` | 云服务凭证 |
|
|
82
|
-
| `*.pdb` 含调试源 / `.dSYM` | 调试符号文件 |
|
|
83
|
-
|
|
84
|
-
`check_*_publish.sh` 命中致命级 → 输出 `[CRITICAL]` 并提示用户立即从 registry 下架。
|
|
85
|
-
|
|
86
|
-
## 校验自动化
|
|
87
|
-
|
|
88
|
-
每次 `pre-publish` 钩子建议接 skill:
|
|
89
|
-
|
|
90
|
-
**Python**(`pyproject.toml`):
|
|
91
|
-
|
|
92
|
-
```toml
|
|
93
|
-
# 暂无标准 prepublish hook,推荐 Makefile / justfile
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
**npm**(`package.json`):
|
|
97
|
-
|
|
98
|
-
```json
|
|
99
|
-
{
|
|
100
|
-
"scripts": {
|
|
101
|
-
"prepublishOnly": "pnpm build && npm pack --dry-run && dwy-sdk-spec check"
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
(注:`dwy-sdk-spec check` 是未来 CLI 子命令计划,当前在 Claude Code 中触发 skill)
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
# Python 商业版 SDK 完整打包指南
|
|
2
|
-
|
|
3
|
-
目标:发布到 PyPI 的 wheel 内**不含 `.py` 源文件**,只含编译后的 `.so` 与必要类型存根。
|
|
4
|
-
|
|
5
|
-
## 决策树
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
模块类型
|
|
9
|
-
├── 公开 API 入口(如 mypkg/__init__.py)→ 保留 .py(用户要 import)
|
|
10
|
-
├── 内部实现(_ 开头,如 mypkg/_engine.py)→ 编译为 .so
|
|
11
|
-
└── 类型存根(.pyi)→ 保留(用户 IDE 提示)
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
## 工具选择
|
|
15
|
-
|
|
16
|
-
| 工具 | 优势 | 推荐场景 |
|
|
17
|
-
|---|---|---|
|
|
18
|
-
| **Cython** | 成熟、setuptools 集成无缝、编译快 | **默认选择**,纯 Python → .so |
|
|
19
|
-
| Nuitka | 优化更激进、支持整包编译 | 大型业务逻辑、想编译整个包 |
|
|
20
|
-
|
|
21
|
-
下面以 Cython 为准。
|
|
22
|
-
|
|
23
|
-
## 项目结构示例
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
mypkg/ # 包根目录
|
|
27
|
-
├── pyproject.toml
|
|
28
|
-
├── MANIFEST.in
|
|
29
|
-
├── .gitignore
|
|
30
|
-
├── src/
|
|
31
|
-
│ └── mypkg/
|
|
32
|
-
│ ├── __init__.py # 公开入口(保留 .py,re-export)
|
|
33
|
-
│ ├── client.py # 公开 API(保留 .py)
|
|
34
|
-
│ ├── _engine.py # 内部核心(编译为 .so)
|
|
35
|
-
│ ├── _engine.pyi # 类型存根(保留)
|
|
36
|
-
│ ├── _utils.py # 内部工具(编译为 .so)
|
|
37
|
-
│ └── _utils.pyi # 类型存根(保留)
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## pyproject.toml 配置
|
|
41
|
-
|
|
42
|
-
```toml
|
|
43
|
-
[build-system]
|
|
44
|
-
requires = ["setuptools>=68.0", "Cython>=3.0"]
|
|
45
|
-
build-backend = "setuptools.build_meta"
|
|
46
|
-
|
|
47
|
-
[project]
|
|
48
|
-
name = "mypkg"
|
|
49
|
-
version = "1.0.0"
|
|
50
|
-
requires-python = ">=3.11"
|
|
51
|
-
|
|
52
|
-
[tool.setuptools]
|
|
53
|
-
include-package-data = true
|
|
54
|
-
zip-safe = false
|
|
55
|
-
|
|
56
|
-
[tool.setuptools.packages.find]
|
|
57
|
-
where = ["src"]
|
|
58
|
-
|
|
59
|
-
[tool.setuptools.package-data]
|
|
60
|
-
mypkg = ["*.pyi", "py.typed"]
|
|
61
|
-
|
|
62
|
-
[tool.setuptools.exclude-package-data]
|
|
63
|
-
mypkg = [
|
|
64
|
-
"_*.py", # 排除以 _ 开头的源文件(已编译为 .so)
|
|
65
|
-
"*.c", # Cython 中间产物
|
|
66
|
-
"*.pyx", # Cython 源
|
|
67
|
-
"*.pyc",
|
|
68
|
-
"__pycache__/*",
|
|
69
|
-
]
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## setup.py(Cython 入口)
|
|
73
|
-
|
|
74
|
-
```python
|
|
75
|
-
from setuptools import setup
|
|
76
|
-
from Cython.Build import cythonize
|
|
77
|
-
from pathlib import Path
|
|
78
|
-
|
|
79
|
-
# 找所有 _ 开头的 .py 模块(命名约定:内部模块用 _ 前缀)
|
|
80
|
-
internal_modules = [
|
|
81
|
-
str(p) for p in Path("src/mypkg").glob("_*.py")
|
|
82
|
-
if p.name != "__init__.py"
|
|
83
|
-
]
|
|
84
|
-
|
|
85
|
-
setup(
|
|
86
|
-
ext_modules=cythonize(
|
|
87
|
-
internal_modules,
|
|
88
|
-
compiler_directives={"language_level": "3"},
|
|
89
|
-
),
|
|
90
|
-
)
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
## MANIFEST.in
|
|
94
|
-
|
|
95
|
-
```
|
|
96
|
-
graft src
|
|
97
|
-
include README.md LICENSE py.typed
|
|
98
|
-
include src/mypkg/*.pyi
|
|
99
|
-
|
|
100
|
-
# 全局排除源码与中间产物
|
|
101
|
-
global-exclude _*.py
|
|
102
|
-
global-exclude *.pyx *.pxd *.c
|
|
103
|
-
global-exclude *.pyc *.pyo
|
|
104
|
-
global-exclude __pycache__ .DS_Store
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
`graft src` 含整个 src/,然后 `global-exclude _*.py` 排掉内部源;公开 `.py` 保留(如 `__init__.py` / `client.py` 不以 `_` 开头)。
|
|
108
|
-
|
|
109
|
-
## 构建命令
|
|
110
|
-
|
|
111
|
-
```bash
|
|
112
|
-
# 清理旧产物
|
|
113
|
-
rm -rf build/ dist/ src/*.egg-info/
|
|
114
|
-
|
|
115
|
-
# 编译 + 打包
|
|
116
|
-
python -m build
|
|
117
|
-
|
|
118
|
-
# 验证 wheel 内不含 _ 开头的 .py
|
|
119
|
-
unzip -l dist/*.whl | grep -E '_.*\.py$' && echo "FAIL: source leaked" || echo "OK"
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
## 验收清单(流程 B 用)
|
|
123
|
-
|
|
124
|
-
| 检查项 | 命令 |
|
|
125
|
-
|---|---|
|
|
126
|
-
| pyproject.toml 含 Cython | `grep -E 'cython\|Cython' pyproject.toml` |
|
|
127
|
-
| `_*.so` 存在 | `find src -name '_*.so' -type f` 应该有输出 |
|
|
128
|
-
| MANIFEST.in 排除源码 | `grep -E 'global-exclude.*_\*\.py' MANIFEST.in` |
|
|
129
|
-
| wheel 内无 `_*.py` | `unzip -l dist/*.whl \| grep -E '_.*\.py$'` 应该为空 |
|
|
130
|
-
| .gitignore 含编译产物 | `grep -E '^\*\.so\b\|^build/\b\|^dist/\b' .gitignore` |
|
|
131
|
-
|
|
132
|
-
## 常见踩坑
|
|
133
|
-
|
|
134
|
-
| 现象 | 原因 | 修复 |
|
|
135
|
-
|---|---|---|
|
|
136
|
-
| wheel 里有 `.py` 源 | `exclude-package-data` 没匹配到 / MANIFEST.in 缺 global-exclude | 同时配 setup 配置 + MANIFEST.in |
|
|
137
|
-
| 装完后 `ImportError: cannot import name '_engine'` | `__init__.py` 用了 `from . import _engine` 但 .so 命名空间不对 | 确保 `.so` 文件在包内,名字与 import 路径一致 |
|
|
138
|
-
| `pip install -e .` 后 import 慢 | 开发模式没编译 .so,跑了 .py | 开发用 `python setup.py build_ext --inplace` 触发编译 |
|
|
139
|
-
| 跨平台 wheel(manylinux / macOS) | 单平台编译产物只能装到对应平台 | 用 `cibuildwheel`(项目已有 dwy-github-action-publish skill) |
|
|
140
|
-
|
|
141
|
-
## 参考 dwy-shared 内已有 SDK
|
|
142
|
-
|
|
143
|
-
`backend/`(`dwyeapi`)当前是**开源版**(pyproject.toml 无 Cython 配置)。若要转商业版:
|
|
144
|
-
1. 把 `src/dwyeapi/security.py` / `database.py` 重命名为 `_security.py` / `_database.py`
|
|
145
|
-
2. `__init__.py` 加 re-export 维持公开 API
|
|
146
|
-
3. 加 Cython 配置、MANIFEST.in、setup.py
|
|
147
|
-
4. 重新发布 → 装完后用户 import 路径不变,但拿不到 .py 源
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
# SDK 接口注释敏感模式清单
|
|
2
|
-
|
|
3
|
-
`check_comments.py` 的规则源。SDK 对外注释(Python docstring、JSDoc、TSDoc)**只写**功能含义、入参格式、返回值、异常,下列模式一律视为泄露。
|
|
4
|
-
|
|
5
|
-
## 模式表
|
|
6
|
-
|
|
7
|
-
| 模式 ID | 正则 | 风险 | 误报豁免(如有) |
|
|
8
|
-
|---|---|---|---|
|
|
9
|
-
| `internal-domain` | `[\w-]+\.(internal\|corp\|local\|intranet)\b` | 暴露内网域名结构 | 出现在 example.com / your-domain 等示例语 → 视为示例 |
|
|
10
|
-
| `private-ip` | `\b(10\.\d+\.\d+\.\d+\|192\.168\.\d+\.\d+\|172\.(1[6-9]\|2\d\|3[01])\.\d+\.\d+)\b` | 暴露内网 IP | — |
|
|
11
|
-
| `sql-statement` | `\b(SELECT\|UPDATE\|DELETE\|INSERT)\b[^.]*\b(FROM\|WHERE\|SET\|INTO)\b` | 暴露表结构、查询逻辑 | 行含 `example`/`e.g.` 视作示例语 |
|
|
12
|
-
| `redis-key-pattern` | `\b(cache\|redis\|fmt\|lock\|queue):[a-z_]+:` | 暴露缓存键 schema | — |
|
|
13
|
-
| `jira-ticket` | `\b[A-Z]{2,6}-\d{2,6}\b` | 暴露内部工单系统 | 行含「示例」「example」豁免 |
|
|
14
|
-
| `internal-service` | `\b[a-z_]+_(service\|server\|grpc\|rpc)_(v\d\|prod\|stg\|dev)\b` | 暴露内部服务命名 | — |
|
|
15
|
-
| `service-port` | `:(\d{4,5})\b` 且行内含 `connect\|server\|host\|endpoint\|address` | 暴露内网服务端口 | 默认端口 80/443/8080 豁免,example 示例豁免 |
|
|
16
|
-
| `internal-email` | `[\w.+-]+@(?!example\.com\|gmail\.com\|outlook\.com)[\w.-]+\.[a-z]{2,}` | 暴露员工邮箱 | 公开公司域名(github.io 等)豁免 |
|
|
17
|
-
| `aws-arn` | `arn:aws:[a-z0-9-]+:[a-z0-9-]*:\d+:[a-zA-Z0-9-_/:]+` | 暴露 AWS 账号 ID 与资源 | — |
|
|
18
|
-
| `cred-keyword` | `\b(API_KEY\|TOKEN\|SECRET\|PASSWORD\|PRIVATE_KEY)\s*[=:]\s*['"][\w-]+['"]` | 注释里硬编码凭证 | 占位 `xxx` / `<your-token>` 豁免 |
|
|
19
|
-
| `aws-key` | `\bAKIA[0-9A-Z]{16}\b` | AWS Access Key ID | — |
|
|
20
|
-
|
|
21
|
-
## 正例 vs 反例
|
|
22
|
-
|
|
23
|
-
### Python docstring
|
|
24
|
-
|
|
25
|
-
**反例**:
|
|
26
|
-
|
|
27
|
-
```python
|
|
28
|
-
def get_user(user_id: str):
|
|
29
|
-
"""
|
|
30
|
-
Connect to https://users.internal.corp.com/v2/profile via gRPC.
|
|
31
|
-
Query SELECT * FROM users_prod WHERE id = ? with cache key cache:user:{id}.
|
|
32
|
-
Owner: john.doe@anthropic.io. See PAY-1234 for context.
|
|
33
|
-
"""
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
**正例**:
|
|
37
|
-
|
|
38
|
-
```python
|
|
39
|
-
def get_user(user_id: str):
|
|
40
|
-
"""
|
|
41
|
-
获取用户基本资料。
|
|
42
|
-
|
|
43
|
-
Args:
|
|
44
|
-
user_id: 用户唯一标识符(UUID 格式)。
|
|
45
|
-
|
|
46
|
-
Returns:
|
|
47
|
-
UserProfile,含 name / email / created_at 字段。
|
|
48
|
-
|
|
49
|
-
Raises:
|
|
50
|
-
UserNotFoundError: user_id 不存在时抛出。
|
|
51
|
-
AuthenticationError: 当前会话无权限读取该用户资料。
|
|
52
|
-
|
|
53
|
-
Example:
|
|
54
|
-
>>> user = get_user("user-123")
|
|
55
|
-
>>> user.name
|
|
56
|
-
'Alice'
|
|
57
|
-
"""
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### TypeScript JSDoc
|
|
61
|
-
|
|
62
|
-
**反例**:
|
|
63
|
-
|
|
64
|
-
```typescript
|
|
65
|
-
/**
|
|
66
|
-
* Fetch user from db.internal.corp:5432 (table users_prod).
|
|
67
|
-
* Uses Redis cache key fmt:user:{id} ttl 3600s.
|
|
68
|
-
* Fallback to backup_db at 10.0.0.5:5432 if primary down.
|
|
69
|
-
* See JIRA USR-456, contact #user-platform on internal Slack.
|
|
70
|
-
*/
|
|
71
|
-
export async function fetchUser(id: string): Promise<UserProfile> { ... }
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
**正例**:
|
|
75
|
-
|
|
76
|
-
```typescript
|
|
77
|
-
/**
|
|
78
|
-
* 获取用户基本资料。
|
|
79
|
-
*
|
|
80
|
-
* @param id 用户唯一标识符(UUID 格式)
|
|
81
|
-
* @returns 用户资料对象,含 name / email / created_at 字段
|
|
82
|
-
* @throws {UserNotFoundError} id 不存在时抛出
|
|
83
|
-
* @throws {AuthenticationError} 当前会话无权限读取该用户资料
|
|
84
|
-
*
|
|
85
|
-
* @example
|
|
86
|
-
* ```ts
|
|
87
|
-
* const user = await fetchUser("user-123");
|
|
88
|
-
* console.log(user.name);
|
|
89
|
-
* ```
|
|
90
|
-
*/
|
|
91
|
-
export async function fetchUser(id: string): Promise<UserProfile> { ... }
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## 应该写什么 vs 不应该写什么
|
|
95
|
-
|
|
96
|
-
| 类别 | 应该写 | 不应该写 |
|
|
97
|
-
|---|---|---|
|
|
98
|
-
| 接口功能 | 业务语义(「获取用户资料」) | 实现路径(「调用 gRPC service xxx」) |
|
|
99
|
-
| 入参 | 类型、格式、约束(UUID、长度上限) | 上游表字段、内部 schema 字段名 |
|
|
100
|
-
| 返回 | 字段语义 | 来自哪张表、哪个缓存键 |
|
|
101
|
-
| 异常 | 业务异常类、触发条件 | 数据库连接错误细节、内部 RPC 失败码 |
|
|
102
|
-
| 示例 | 公开占位(`user-123` / `example.com`) | 真实用户 ID、真实邮箱、内网域名 |
|
|
103
|
-
| 链接 | 公开文档 URL、相对路径文档 | 内网 wiki、JIRA、Slack、Confluence 链接 |
|
|
104
|
-
|
|
105
|
-
## 行内豁免约定
|
|
106
|
-
|
|
107
|
-
误报场景在该行追加注释:
|
|
108
|
-
|
|
109
|
-
- Python:`# sdk-spec: ignore`
|
|
110
|
-
- TS/JS:`// sdk-spec: ignore`
|
|
111
|
-
|
|
112
|
-
豁免**单行**,不豁免整段。要长期豁免某文件 → 在 `<project_root>/.dwy/sdk-spec/config.json` 加 `ignore_files: ["path/to/file.py"]`(未来支持,当前手动用行内豁免)。
|