hexo-deployer-wrangler 1.0.3

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 (3) hide show
  1. package/README.md +246 -0
  2. package/index.js +1 -0
  3. package/package.json +32 -0
package/README.md ADDED
@@ -0,0 +1,246 @@
1
+ # hexo-deployer-wrangler
2
+
3
+ 基于 [Wrangler CLI (v4+)](https://developers.cloudflare.com/workers/wrangler/) 将 Hexo 站点部署到 [Cloudflare Pages](https://pages.cloudflare.com/) 和 [Cloudflare Workers](https://workers.cloudflare.com/) 的插件。
4
+
5
+ > 要求 Node.js >= 18.0.0
6
+
7
+ ## 前置条件
8
+
9
+ - **Pages 模式**:在 Cloudflare 控制台中已创建好 [Pages 项目](https://pages.cloudflare.com/)。
10
+ - **Worker 模式**:项目根目录存在 `wrangler.toml` 配置文件,且已通过 `wrangler deploy` 创建过 Worker。
11
+ - Cloudflare 认证(以下三种方式任选其一):
12
+ - **API Token**(推荐):拥有 **Pages:Edit** / **Workers Scripts:Edit** 权限的 Token,[创建地址](https://dash.cloudflare.com/profile/api-tokens)
13
+ - **本地登录**:运行 `npx wrangler login` 完成 OAuth 登录,凭证保存在本地 `~/.wrangler/` 目录
14
+ - **Global API Key**:通过 `CLOUDFLARE_API_KEY` + `CLOUDFLARE_EMAIL` 环境变量提供
15
+
16
+ ## 安装
17
+
18
+ ```bash
19
+ npm install hexo-deployer-wrangler
20
+ ```
21
+
22
+ ## 配置
23
+
24
+ ### 1. 认证方式
25
+
26
+ 插件支持三种认证方式,按优先级依次为:
27
+
28
+ | 优先级 | 方式 | 说明 |
29
+ |---|---|---|
30
+ | 1 | API Token | 设置 `CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID` 环境变量 |
31
+ | 2 | Global API Key | 设置 `CLOUDFLARE_API_KEY` + `CLOUDFLARE_EMAIL` + `CLOUDFLARE_ACCOUNT_ID` 环境变量 |
32
+ | 3 | 本地 OAuth 登录 | 运行 `npx wrangler login` 后在 `~/.wrangler/` 目录中保存的凭证 |
33
+
34
+ **方式一:API Token(推荐)**
35
+
36
+ ```bash
37
+ export CLOUDFLARE_API_TOKEN="你的-api-token"
38
+ export CLOUDFLARE_ACCOUNT_ID="你的-account-id"
39
+ ```
40
+
41
+ **方式二:本地 OAuth 登录**
42
+
43
+ ```bash
44
+ npx wrangler login
45
+ # 浏览器中完成授权后即可使用,无需设置环境变量
46
+ ```
47
+
48
+ **方式三:Global API Key**
49
+
50
+ ```bash
51
+ export CLOUDFLARE_API_KEY="你的-global-api-key"
52
+ export CLOUDFLARE_EMAIL="你的-email@example.com"
53
+ export CLOUDFLARE_ACCOUNT_ID="你的-account-id"
54
+ ```
55
+
56
+ > Account ID 也可以通过项目根目录的 `wrangler.toml` 文件中的 `account_id` 字段提供。
57
+
58
+ ### 2. 修改 Hexo 配置
59
+
60
+ 在 `_config.yml` 中添加 deploy 段落。通过 `target` 切换部署目标(默认 `pages`):
61
+
62
+ ```yaml
63
+ # 部署到 Cloudflare Pages
64
+ deploy:
65
+ type: wrangler
66
+ target: pages
67
+ project_name: my-hexo-blog
68
+
69
+ # 部署到 Cloudflare Workers
70
+ deploy:
71
+ type: wrangler
72
+ target: worker
73
+ # Worker 配置由 wrangler.toml 管理,此处提供覆盖选项
74
+ ```
75
+
76
+ ## 配置项说明
77
+
78
+ ### 通用配置
79
+
80
+ | 配置项 | 类型 | 默认值 | 说明 |
81
+ |---|---|---|---|
82
+ | `target` | string | `pages` | 部署目标:`pages` 或 `worker` |
83
+ | `compat_date` | string | — | 传给 wrangler 的兼容性日期 |
84
+ | `compat_flags` | string\|array | — | 兼容性标志(逗号分隔字符串或数组) |
85
+
86
+ ### Pages 专用配置
87
+
88
+ | 配置项 | 类型 | 默认值 | 说明 |
89
+ |---|---|---|---|
90
+ | `project_name` | string | 必填 | Cloudflare Pages 项目名称 |
91
+ | `branch` | string | `main` | 部署时记录的 Git 分支名 |
92
+ | `commit_dirty` | boolean | `false` | 工作区有未提交更改时是否仍允许部署 |
93
+ | `commit_hash` | string | — | 自定义部署记录的 commit hash |
94
+ | `commit_message` | string | — | 自定义部署记录的 commit message |
95
+ | `skip_bundle` | boolean | `false` | 跳过 wrangler 的打包步骤(建议 Hexo 开启) |
96
+
97
+ ### Worker 专用配置
98
+
99
+ | 配置项 | 类型 | 默认值 | 说明 |
100
+ |---|---|---|---|
101
+ | `env` | string | — | 部署环境(如 `production`、`staging`) |
102
+ | `name` | string | — | Worker 名称,覆盖 wrangler.toml 中的设置 |
103
+ | `dry_run` | boolean | `false` | 空跑模式,只输出将部署的内容 |
104
+ | `tsconfig` | string | — | TypeScript 配置文件路径 |
105
+ | `outdir` | string | — | Worker 打包产物输出目录 |
106
+ | `routes` | string\|array | — | 路由列表(逗号分隔或数组) |
107
+ | `vars` | object\|string | — | Worker 变量(对象或 `key:value,...` 格式字符串) |
108
+
109
+ ### 完整配置示例
110
+
111
+ ```yaml
112
+ # Pages 部署
113
+ deploy:
114
+ type: wrangler
115
+ target: pages
116
+ project_name: my-hexo-blog
117
+ branch: production
118
+ commit_dirty: true
119
+ skip_bundle: true
120
+ # compat_date: '2025-01-01'
121
+ # compat_flags: 'nodejs_compat,streams'
122
+
123
+ # Worker 部署
124
+ deploy:
125
+ type: wrangler
126
+ target: worker
127
+ env: production
128
+ dry_run: false
129
+ routes: 'example.com/*,api.example.com/*'
130
+ vars:
131
+ API_URL: 'https://api.example.com'
132
+ DEBUG: 'false'
133
+ # 或者 vars: 'API_URL:https://api.example.com,DEBUG:false'
134
+ # compat_date: '2025-01-01'
135
+ # compat_flags: 'nodejs_compat'
136
+ ```
137
+
138
+ ## 配置优先级
139
+
140
+ 配置项按以下优先级解析(高到低):
141
+
142
+ | 优先级 | 来源 | 说明 |
143
+ |---|---|---|
144
+ | 1 | CLI 参数 | 通过 `hexo deploy -- <key> <value>` 传入 |
145
+ | 2 | `_config.yml` | Hexo 博客的 deploy 配置段 |
146
+ | 3 | `wrangler.toml` | 博客根目录的 Wrangler 配置文件(自动读取) |
147
+
148
+ ### wrangler.toml 自动映射
149
+
150
+ 插件会自动读取博客根目录的 `wrangler.toml` 作为默认配置。以下字段会自动映射:
151
+
152
+ | wrangler.toml 字段 | 对应 _config.yml 配置项 | 适用目标 |
153
+ |---|---|---|
154
+ | `name` | `project_name` (Pages) / `name` (Worker) | Pages / Worker |
155
+ | `account_id` | `CLOUDFLARE_ACCOUNT_ID` 环境变量 | 通用 |
156
+ | `compatibility_date` | `compat_date` | 通用 |
157
+ | `compatibility_flags` | `compat_flags` | 通用 |
158
+ | `[vars]` | `vars` | Worker |
159
+ | `[[routes]]` | `routes` | Worker |
160
+ | `[env.<name>]` | 对应环境的覆盖配置 | Worker |
161
+
162
+ 示例:只需在 `wrangler.toml` 中维护一份配置,`_config.yml` 中只写最简内容。
163
+
164
+ ```toml
165
+ # wrangler.toml
166
+ name = "my-hexo-site"
167
+ account_id = "abcd1234..."
168
+ compatibility_date = "2025-01-01"
169
+ compatibility_flags = ["nodejs_compat"]
170
+
171
+ [vars]
172
+ API_URL = "https://api.example.com"
173
+
174
+ [[routes]]
175
+ pattern = "example.com/*"
176
+ ```
177
+
178
+ ```yaml
179
+ # _config.yml - 极简配置,其余全从 wrangler.toml 读取
180
+ deploy:
181
+ type: wrangler
182
+ target: worker
183
+ env: production
184
+ ```
185
+
186
+ ## 使用方式
187
+
188
+ 构建并部署:
189
+
190
+ ```bash
191
+ hexo generate
192
+ hexo deploy
193
+ ```
194
+
195
+ 或合并为一行命令:
196
+
197
+ ```bash
198
+ hexo generate --deploy
199
+ # 或者
200
+ hexo deploy --generate
201
+ ```
202
+
203
+ ## 工作原理
204
+
205
+ **Pages 模式** (`target: pages`):
206
+ 1. 执行 `hexo generate` 在 `public/` 目录中生成静态文件。
207
+ 2. 调用 `wrangler pages deploy <public_dir>` 将构建产物上传至 Cloudflare Pages。
208
+ 3. Wrangler 自动处理资源哈希、CDN 分发和 DNS 路由。
209
+
210
+ **Worker 模式** (`target: worker`):
211
+ 1. 调用 `wrangler deploy` 部署 Worker 脚本(配置由 `wrangler.toml` 提供)。
212
+ 2. 通过 `_config.yml` 中的 Worker 专用配置可覆盖或补充 CLI 参数。
213
+
214
+ 统一使用 `npx wrangler` 命令行工具,工作目录锁定为博客根目录(确保 wrangler 能读取 `wrangler.toml`),跨平台兼容 Windows / macOS / Linux。
215
+
216
+ ## 常见问题
217
+
218
+ ### 提示 `CLOUDFLARE_API_TOKEN` 未设置
219
+
220
+ 设置对应环境变量,或通过 `wrangler login` 创建全局认证配置。在 CI/CD 环境中建议使用 API Token 方式。
221
+
222
+ ### 提示 `CLOUDFLARE_ACCOUNT_ID` 未设置
223
+
224
+ 在 [Cloudflare Dashboard](https://dash.cloudflare.com/) 侧边栏找到 Account ID,或运行:
225
+
226
+ ```bash
227
+ wrangler whoami
228
+ ```
229
+
230
+ ### 提示找不到项目
231
+
232
+ 确认 `_config.yml` 中的 `project_name` 与 Cloudflare Pages 中已创建的项目名称一致。可在 [Cloudflare Dashboard](https://dash.cloudflare.com/pages) 中创建新项目。
233
+
234
+ ### 本地登录后仍未生效
235
+
236
+ 确认 `~/.wrangler/config/default.toml` 文件存在且包含认证信息(`access_token`、`refresh_token` 等字段)。Windows 用户请注意 `os.homedir()` 在某些终端(如 MSYS)下可能返回非预期路径,插件会优先使用 `USERPROFILE` 环境变量定位。
237
+
238
+ 如果登录过期,重新运行 `npx wrangler login`。
239
+
240
+ ### 部署成功但提示"未检测到认证方式"
241
+
242
+ 这是插件启动时的预检警告,实际部署由 wrangler 自行完成。如果 `npx wrangler whoami` 能正常输出则表示认证无问题,可忽略该警告。该问题通常已在最新版本修复。
243
+
244
+ ## 协议
245
+
246
+ MIT
package/index.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";const{spawn:spawn}=require("child_process"),path=require("path"),fs=require("fs"),os=require("os"),{parse:parseToml}=require("smol-toml");function readWranglerToml(e){const r=path.join(e||"","wrangler.toml");try{return parseToml(fs.readFileSync(r,"utf-8"))}catch(e){return null}}function buildPagesArgs(e,r,o){const n=e.config.deploy||{},s=["pages","deploy",path.resolve(e.public_dir||"public")],t=r.project_name||n.project_name||n.projectName||o&&o.name;t&&s.push("--project-name",t);const c=r.branch||n.branch;c&&s.push("--branch",c);const a=r.commit_hash||n.commit_hash||n.commitHash;a&&s.push("--commit-hash",a);const i=r.commit_message||n.commit_message||n.commitMessage;i&&s.push("--commit-message",i);(void 0!==r.commit_dirty?r.commit_dirty:n.commit_dirty||n.commitDirty)&&s.push("--commit-dirty");return(void 0!==r.skip_bundle?r.skip_bundle:n.skip_bundle||n.skipBundle)&&s.push("--no-bundle"),s}function buildWorkerArgs(e,r){const o=e.config.deploy||{},n=["deploy"],s=r.env||o.env;s&&n.push("--env",s);const t=r.name||o.name;t&&n.push("--name",t);(void 0!==r.dry_run?r.dry_run:o.dry_run||o.dryRun)&&n.push("--dry-run");const c=r.tsconfig||o.tsconfig;c&&n.push("--tsconfig",c);const a=r.outdir||o.outdir;return a&&n.push("--outdir",a),n}function buildArgs(e,r){const o=e.config.deploy||{},n=r.target||o.target||"pages",s=e.base_dir||process.cwd(),t=readWranglerToml(s);return t&&e.log.info("已读取 wrangler.toml 配置"),"worker"===n?{argv:buildWorkerArgs(e,r),baseDir:s}:{argv:buildPagesArgs(e,r,t),baseDir:s}}function runWrangler(e,r,o){return new Promise((n,s)=>{const t="win32"===process.platform?"npx.cmd":"npx";r.log.info("npx wrangler %s",e.join(" "));const c=spawn(t,["wrangler",...e],{stdio:"inherit",env:process.env,cwd:o||process.cwd(),shell:"win32"===process.platform});c.on("close",e=>{0===e?n():s(new Error(`wrangler exited with code ${e}`))}),c.on("error",s)})}function checkLocalLogin(){let e=process.env.WRANGLER_HOME;e||(e="win32"===process.platform&&process.env.USERPROFILE?path.join(process.env.USERPROFILE,".wrangler"):path.join(os.homedir(),".wrangler"));const r=path.join(e,"config","default.toml");try{const e=parseToml(fs.readFileSync(r,"utf-8"));return!!(e.access_token||e.oauth_token||e.refresh_token||e.api_token||e.oauth&&(e.oauth.refresh_token||e.oauth.access_token))}catch(e){return!1}}function checkWranglerTomlAccount(e){const r=readWranglerToml(e);return!(!r||!r.account_id)}function validate(e){const r=!!process.env.CLOUDFLARE_API_TOKEN,o=!!process.env.CLOUDFLARE_API_KEY,n=!!process.env.CLOUDFLARE_ACCOUNT_ID,s=checkLocalLogin(),t=checkWranglerTomlAccount(e.base_dir||process.cwd());r?e.log.info("检测到 CLOUDFLARE_API_TOKEN 环境变量,使用 API Token 认证"):o?e.log.info("检测到 CLOUDFLARE_API_KEY 环境变量,使用 Global API Key 认证"):s&&e.log.info("检测到本地 wrangler 登录状态,使用 OAuth 认证"),n?e.log.info("检测到 CLOUDFLARE_ACCOUNT_ID: %s",process.env.CLOUDFLARE_ACCOUNT_ID):t&&e.log.info("检测到 wrangler.toml 中的 account_id"),r||o||s||(e.log.warn(""),e.log.warn("⚠ 未检测到任何 Cloudflare 认证方式,部署可能失败!"),e.log.warn(" 方式1 (推荐): 设置 CLOUDFLARE_API_TOKEN 和 CLOUDFLARE_ACCOUNT_ID 环境变量"),e.log.warn(" 方式2: 运行 npx wrangler login 进行本地 OAuth 登录"),e.log.warn(" 方式3: 设置 CLOUDFLARE_API_KEY 和 CLOUDFLARE_EMAIL 环境变量"),e.log.warn("")),n||t||e.log.info("未显式设置 CLOUDFLARE_ACCOUNT_ID,wrangler 将尝试自动推断")}function deploy(e,r){const o=this,n=async()=>{try{validate(o);const r="worker"===(e.target||o.config.deploy.target||"pages")?"Cloudflare Workers":"Cloudflare Pages";o.log.info("Deploying to %s via Wrangler...",r);const{argv:n,baseDir:s}=buildArgs(o,e);o.log.info("wrangler %s",n.join(" ")),await runWrangler(n,o,s),o.log.info("Deployment successful!")}catch(e){if(o.log.error("Deployment failed: %s",e.message),r)return void r(e);throw e}r&&r()};if("function"!=typeof r)return n();n()}hexo.extend.deployer.register("wrangler",deploy);
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "hexo-deployer-wrangler",
3
+ "version": "1.0.3",
4
+ "description": "Hexo deployer plugin for Cloudflare Pages via Wrangler CLI (v3+)",
5
+ "main": "index.js",
6
+ "keywords": [
7
+ "hexo",
8
+ "deployer",
9
+ "cloudflare",
10
+ "wrangler",
11
+ "pages"
12
+ ],
13
+ "author": "",
14
+ "license": "MIT",
15
+ "peerDependencies": {
16
+ "hexo": ">=5.0.0"
17
+ },
18
+ "dependencies": {
19
+ "smol-toml": "^1.6.1",
20
+ "wrangler": "^4.91.0"
21
+ },
22
+ "files": [
23
+ "index.js"
24
+ ],
25
+ "engines": {
26
+ "node": ">=18.0.0"
27
+ },
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git+https://github.com/llxlr/hexo-deployer-wrangler.git"
31
+ }
32
+ }