electron-updater-for-render 1.0.0 → 1.1.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/README.zh-CN.md +24 -26
- package/Readme.md +23 -26
- package/dist/{builder/vite-plugin.cjs → bin/cli.cjs} +81 -26
- package/dist/bin/cli.d.ts +2 -0
- package/dist/bin/cli.js +164 -0
- package/dist/builder/index.cjs +7 -2
- package/dist/builder/index.d.ts +1 -0
- package/dist/builder/index.js +5 -1
- package/package.json +7 -13
- package/dist/builder/vite-plugin.d.ts +0 -5
- package/dist/builder/vite-plugin.js +0 -96
package/README.zh-CN.md
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
npm install electron-updater-for-render
|
|
28
28
|
|
|
29
29
|
# 打包阶段依赖(在渲染层项目中安装)
|
|
30
|
-
npm install -D asar
|
|
30
|
+
npm install -D asar
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
---
|
|
@@ -38,7 +38,7 @@ npm install -D asar cross-env
|
|
|
38
38
|
┌─────────────────────────────────────────────────────┐
|
|
39
39
|
│ 渲染层项目(如 Vue 工程) │
|
|
40
40
|
│ npm run build:update │
|
|
41
|
-
│ →
|
|
41
|
+
│ → 原生 build 命令 → 调用 CLI打包 ASAR → 生成 latest.json │
|
|
42
42
|
└───────────────┬─────────────────────────────────────┘
|
|
43
43
|
│ 上传 dist_updates/ 到服务器
|
|
44
44
|
▼
|
|
@@ -59,23 +59,19 @@ npm install -D asar cross-env
|
|
|
59
59
|
|
|
60
60
|
## 🛠️ 完整接入指南
|
|
61
61
|
|
|
62
|
-
### 第一步 —
|
|
62
|
+
### 第一步 — 渲染工程:配置并声明生成规则
|
|
63
|
+
|
|
64
|
+
在您的任何前端项目根目录下(无论 Vite, Webpack,亦或普通网页)新建 `updater.config.ts`:
|
|
63
65
|
|
|
64
66
|
```typescript
|
|
65
|
-
|
|
66
|
-
import { defineConfig } from 'vite'
|
|
67
|
-
import { electronRenderUpdater } from 'electron-updater-for-render/vite'
|
|
67
|
+
import { defineConfig } from 'electron-updater-for-render/builder'
|
|
68
68
|
|
|
69
69
|
export default defineConfig({
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
// packageJsonPath: './package.json' // 可选:自定义 package.json 路径
|
|
76
|
-
// forceUpdate: 'prompt' // 可选:'prompt' | 'silent',仅 P0 紧急修复时使用
|
|
77
|
-
})
|
|
78
|
-
]
|
|
70
|
+
outDir: './dist', // 必填:您的构建输出目录
|
|
71
|
+
updatesDir: './dist_updates', // 可选:更新包输出目录(默认 './dist_updates')
|
|
72
|
+
// version: '1.2.3' // 可选:显式指定版本号(优先级高于 package.json)
|
|
73
|
+
// packageJsonPath: './package.json' // 可选:自定义 package.json 路径
|
|
74
|
+
// forceUpdate: 'prompt' // 可选:'prompt' | 'silent',仅 P0 紧急修复时使用
|
|
79
75
|
})
|
|
80
76
|
```
|
|
81
77
|
|
|
@@ -84,16 +80,15 @@ export default defineConfig({
|
|
|
84
80
|
2. `packageJsonPath` 所指向文件中的 `version`
|
|
85
81
|
3. 自动检测:`process.cwd()/package.json`(默认,零配置)
|
|
86
82
|
|
|
87
|
-
### 第二步 —
|
|
83
|
+
### 第二步 — 渲染工程:串联您的构建命令
|
|
88
84
|
|
|
89
|
-
在 `package.json`
|
|
85
|
+
在 `package.json` 中配置 CLI 执行链:
|
|
90
86
|
|
|
91
87
|
```json
|
|
92
88
|
{
|
|
93
89
|
"scripts": {
|
|
94
|
-
"
|
|
95
|
-
"build": "
|
|
96
|
-
"build:update": "cross-env ELECTRON_PACK_UPDATE=1 vite build"
|
|
90
|
+
"build": "您的原生打包命令,如 vite build 或 webpack",
|
|
91
|
+
"build:update": "npm run build && electron-updater-for-render"
|
|
97
92
|
}
|
|
98
93
|
}
|
|
99
94
|
```
|
|
@@ -101,7 +96,10 @@ export default defineConfig({
|
|
|
101
96
|
| 命令 | 行为 |
|
|
102
97
|
|---|---|
|
|
103
98
|
| `npm run build` | 普通前端打包,**不生成 ASAR**,与原有流程完全一致 |
|
|
104
|
-
| `npm run build:update` |
|
|
99
|
+
| `npm run build:update` | 触发原生构建 + CLI打包出 ASAR + 生成 `latest.json` |
|
|
100
|
+
|
|
101
|
+
> 💡 **进阶用法**:如果你不想用默认的 `updater.config.ts` 文件名,也可以通过 `-c` 或 `--config` 指定:
|
|
102
|
+
> `"build:update": "npm run build && electron-updater-for-render -c ./config/custom.config.ts"`
|
|
105
103
|
|
|
106
104
|
### 第三步 — 部署更新文件到服务器
|
|
107
105
|
|
|
@@ -279,7 +277,7 @@ const installUpdate = () => {
|
|
|
279
277
|
|
|
280
278
|
## ⚙️ API 参考
|
|
281
279
|
|
|
282
|
-
### `BuilderOptions`(
|
|
280
|
+
### `BuilderOptions`(CLI 配置参数)
|
|
283
281
|
|
|
284
282
|
| 参数 | 类型 | 必填 | 说明 |
|
|
285
283
|
|---|---|---|---|
|
|
@@ -315,8 +313,8 @@ const installUpdate = () => {
|
|
|
315
313
|
当线上出现资损、安全漏洞、核心功能崩溃等 P0 级故障时,通过 `forceUpdate` 剥夺用户的拒绝权:
|
|
316
314
|
|
|
317
315
|
```typescript
|
|
318
|
-
//
|
|
319
|
-
|
|
316
|
+
// updater.config.ts (加入此行)
|
|
317
|
+
export default defineConfig({
|
|
320
318
|
outDir: './dist',
|
|
321
319
|
forceUpdate: 'prompt' // 或 'silent'
|
|
322
320
|
})
|
|
@@ -340,8 +338,8 @@ openssl rsa -in private.pem -pubout -out public.pem
|
|
|
340
338
|
```
|
|
341
339
|
|
|
342
340
|
```typescript
|
|
343
|
-
//
|
|
344
|
-
|
|
341
|
+
// updater.config.ts
|
|
342
|
+
export default defineConfig({ outDir: './dist', privateKeyPath: './private.pem' })
|
|
345
343
|
|
|
346
344
|
// main/index.ts
|
|
347
345
|
import { readFileSync } from 'fs'
|
package/Readme.md
CHANGED
|
@@ -27,7 +27,7 @@ Unlike `electron-updater` which re-downloads the entire app installer, this libr
|
|
|
27
27
|
npm install electron-updater-for-render
|
|
28
28
|
|
|
29
29
|
# asar is required for the build step (in your renderer project)
|
|
30
|
-
npm install -D asar
|
|
30
|
+
npm install -D asar
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
---
|
|
@@ -36,9 +36,8 @@ npm install -D asar cross-env
|
|
|
36
36
|
|
|
37
37
|
```
|
|
38
38
|
┌─────────────────────────────────────────────────────┐
|
|
39
|
-
│ Renderer Project (e.g. Vue) │
|
|
40
39
|
│ npm run build:update │
|
|
41
|
-
│ →
|
|
40
|
+
│ → native build → trigger CLI pack ASAR → latest.json│
|
|
42
41
|
└───────────────┬─────────────────────────────────────┘
|
|
43
42
|
│ Upload dist_updates/ to server
|
|
44
43
|
▼
|
|
@@ -59,23 +58,19 @@ npm install -D asar cross-env
|
|
|
59
58
|
|
|
60
59
|
## 🛠️ Complete Setup Guide
|
|
61
60
|
|
|
62
|
-
### Step 1 — Renderer Project:
|
|
61
|
+
### Step 1 — Renderer Project: Define Config
|
|
62
|
+
|
|
63
|
+
In the root of your frontend project (Vite, Webpack, etc.), create `updater.config.ts`:
|
|
63
64
|
|
|
64
65
|
```typescript
|
|
65
|
-
|
|
66
|
-
import { defineConfig } from 'vite'
|
|
67
|
-
import { electronRenderUpdater } from 'electron-updater-for-render/vite'
|
|
66
|
+
import { defineConfig } from 'electron-updater-for-render/builder'
|
|
68
67
|
|
|
69
68
|
export default defineConfig({
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
// packageJsonPath: './package.json' // Optional: custom package.json path
|
|
76
|
-
// forceUpdate: 'prompt' // Optional: 'prompt' | 'silent' — for P0 mandatory rollouts ONLY
|
|
77
|
-
})
|
|
78
|
-
]
|
|
69
|
+
outDir: './dist', // Required: Your build output directory
|
|
70
|
+
updatesDir: './dist_updates', // Optional: where to write update packages (default: './dist_updates')
|
|
71
|
+
// version: '1.2.3' // Optional: explicit version (overrides package.json)
|
|
72
|
+
// packageJsonPath: './package.json' // Optional: custom package.json path
|
|
73
|
+
// forceUpdate: 'prompt' // Optional: 'prompt' | 'silent' — for P0 mandatory rollouts ONLY
|
|
79
74
|
})
|
|
80
75
|
```
|
|
81
76
|
|
|
@@ -86,20 +81,22 @@ export default defineConfig({
|
|
|
86
81
|
|
|
87
82
|
### Step 2 — Renderer Project: Add Build Script
|
|
88
83
|
|
|
89
|
-
|
|
84
|
+
In your `package.json`, chain your build command with the updater CLI:
|
|
90
85
|
|
|
91
86
|
```json
|
|
92
87
|
{
|
|
93
88
|
"scripts": {
|
|
94
|
-
"
|
|
95
|
-
"build": "
|
|
96
|
-
"build:update": "cross-env ELECTRON_PACK_UPDATE=1 vite build"
|
|
89
|
+
"build": "your native build command (vite build or webpack)",
|
|
90
|
+
"build:update": "npm run build && electron-updater-for-render"
|
|
97
91
|
}
|
|
98
92
|
}
|
|
99
93
|
```
|
|
100
94
|
|
|
101
95
|
> `npm run build` — normal frontend build, **no ASAR packing**
|
|
102
|
-
> `npm run build:update` — builds frontend + packs ASAR + writes `latest.json`
|
|
96
|
+
> `npm run build:update` — builds frontend + CLI packs ASAR + writes `latest.json`
|
|
97
|
+
|
|
98
|
+
> 💡 **Advanced Usage**: The CLI looks for `updater.config.ts` by default. If you use a custom path, pass it via `-c` or `--config`:
|
|
99
|
+
> `"build:update": "npm run build && electron-updater-for-render -c custom/path.config.ts"`
|
|
103
100
|
|
|
104
101
|
### Step 3 — Deploy Update Files
|
|
105
102
|
|
|
@@ -276,7 +273,7 @@ const installUpdate = () => {
|
|
|
276
273
|
|
|
277
274
|
## ⚙️ API Reference
|
|
278
275
|
|
|
279
|
-
### `BuilderOptions` (
|
|
276
|
+
### `BuilderOptions` (CLI Config)
|
|
280
277
|
|
|
281
278
|
| Option | Type | Required | Description |
|
|
282
279
|
|---|---|---|---|
|
|
@@ -312,8 +309,8 @@ const installUpdate = () => {
|
|
|
312
309
|
For P0 incidents where deferral is not an option:
|
|
313
310
|
|
|
314
311
|
```typescript
|
|
315
|
-
//
|
|
316
|
-
|
|
312
|
+
// updater.config.ts
|
|
313
|
+
export default defineConfig({
|
|
317
314
|
outDir: './dist',
|
|
318
315
|
forceUpdate: 'prompt' // or 'silent'
|
|
319
316
|
})
|
|
@@ -337,8 +334,8 @@ openssl rsa -in private.pem -pubout -out public.pem
|
|
|
337
334
|
```
|
|
338
335
|
|
|
339
336
|
```typescript
|
|
340
|
-
//
|
|
341
|
-
|
|
337
|
+
// updater.config.ts
|
|
338
|
+
export default defineConfig({ outDir: './dist', privateKeyPath: './private.pem' })
|
|
342
339
|
|
|
343
340
|
// main/index.ts
|
|
344
341
|
import { readFileSync } from 'fs'
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
"use strict";
|
|
2
3
|
var __create = Object.create;
|
|
3
4
|
var __defProp = Object.defineProperty;
|
|
@@ -5,10 +6,6 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
9
|
var __copyProps = (to, from, except, desc) => {
|
|
13
10
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
11
|
for (let key of __getOwnPropNames(from))
|
|
@@ -25,14 +22,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
22
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
23
|
mod
|
|
27
24
|
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
25
|
|
|
30
|
-
// src/
|
|
31
|
-
var
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
26
|
+
// src/bin/cli.ts
|
|
27
|
+
var import_node_util = require("util");
|
|
28
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
29
|
+
var import_node_fs = __toESM(require("fs"), 1);
|
|
30
|
+
var import_node_module = require("module");
|
|
31
|
+
var import_node_url = require("url");
|
|
36
32
|
|
|
37
33
|
// src/builder/index.ts
|
|
38
34
|
var import_fs = __toESM(require("fs"), 1);
|
|
@@ -109,25 +105,84 @@ async function createUpdatePackage(options) {
|
|
|
109
105
|
console.log(`[RenderUpdater Builder] Info: ${jsonPath}`);
|
|
110
106
|
}
|
|
111
107
|
|
|
112
|
-
// src/
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
108
|
+
// src/bin/cli.ts
|
|
109
|
+
var import_meta = {};
|
|
110
|
+
var require2 = (0, import_node_module.createRequire)(import_meta.url);
|
|
111
|
+
var __filename = (0, import_node_url.fileURLToPath)(import_meta.url);
|
|
112
|
+
async function main() {
|
|
113
|
+
const args = process.argv.slice(2);
|
|
114
|
+
const options = (0, import_node_util.parseArgs)({
|
|
115
|
+
args,
|
|
116
|
+
options: {
|
|
117
|
+
config: { type: "string", short: "c" },
|
|
118
|
+
outDir: { type: "string" },
|
|
119
|
+
version: { type: "string" },
|
|
120
|
+
packageJsonPath: { type: "string" },
|
|
121
|
+
asarName: { type: "string" },
|
|
122
|
+
privateKeyPath: { type: "string" },
|
|
123
|
+
releaseNotesPath: { type: "string" },
|
|
124
|
+
forceUpdate: { type: "string" }
|
|
125
|
+
},
|
|
126
|
+
strict: false
|
|
127
|
+
});
|
|
128
|
+
let configPath = options.values.config;
|
|
129
|
+
const cwd = process.cwd();
|
|
130
|
+
if (!configPath) {
|
|
131
|
+
const defaultConfigs = [
|
|
132
|
+
"updater.config.ts",
|
|
133
|
+
"updater.config.js",
|
|
134
|
+
"updater.config.mjs",
|
|
135
|
+
"updater.config.cjs"
|
|
136
|
+
];
|
|
137
|
+
for (const file of defaultConfigs) {
|
|
138
|
+
if (import_node_fs.default.existsSync(import_node_path.default.join(cwd, file))) {
|
|
139
|
+
configPath = file;
|
|
140
|
+
break;
|
|
120
141
|
}
|
|
121
|
-
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
let fileConfig = {};
|
|
145
|
+
if (configPath && typeof configPath === "string") {
|
|
146
|
+
const fullConfigPath = import_node_path.default.resolve(cwd, configPath);
|
|
147
|
+
if (import_node_fs.default.existsSync(fullConfigPath)) {
|
|
122
148
|
try {
|
|
123
|
-
|
|
149
|
+
const jiti = require2("jiti")(__filename, {
|
|
150
|
+
interopDefault: true,
|
|
151
|
+
cache: false
|
|
152
|
+
});
|
|
153
|
+
const loadedConfig = jiti(fullConfigPath);
|
|
154
|
+
fileConfig = loadedConfig.default || loadedConfig;
|
|
155
|
+
console.log(`[RenderUpdater CLI] Loaded config from ${configPath}`);
|
|
124
156
|
} catch (err) {
|
|
125
|
-
console.error(
|
|
157
|
+
console.error(`[RenderUpdater CLI] Failed to load config from ${configPath}: ${err.message}`);
|
|
158
|
+
process.exit(1);
|
|
126
159
|
}
|
|
160
|
+
} else {
|
|
161
|
+
console.error(`[RenderUpdater CLI] Config file not found at ${configPath}`);
|
|
162
|
+
process.exit(1);
|
|
127
163
|
}
|
|
164
|
+
}
|
|
165
|
+
const finalOptions = {
|
|
166
|
+
...fileConfig
|
|
128
167
|
};
|
|
168
|
+
if (options.values.outDir) finalOptions.outDir = options.values.outDir;
|
|
169
|
+
if (options.values.version) finalOptions.version = options.values.version;
|
|
170
|
+
if (options.values.packageJsonPath) finalOptions.packageJsonPath = options.values.packageJsonPath;
|
|
171
|
+
if (options.values.asarName) finalOptions.asarName = options.values.asarName;
|
|
172
|
+
if (options.values.privateKeyPath) finalOptions.privateKeyPath = options.values.privateKeyPath;
|
|
173
|
+
if (options.values.releaseNotesPath) finalOptions.releaseNotesPath = options.values.releaseNotesPath;
|
|
174
|
+
if (options.values.forceUpdate) {
|
|
175
|
+
finalOptions.forceUpdate = options.values.forceUpdate;
|
|
176
|
+
}
|
|
177
|
+
if (!finalOptions.outDir) {
|
|
178
|
+
console.error("[RenderUpdater CLI] Error: outDir is required. Please specify it in the config file or via --outDir.");
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
await createUpdatePackage(finalOptions);
|
|
183
|
+
} catch (err) {
|
|
184
|
+
console.error(`[RenderUpdater CLI] Failed to build update package: ${err.message}`);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
129
187
|
}
|
|
130
|
-
|
|
131
|
-
0 && (module.exports = {
|
|
132
|
-
electronRenderUpdater
|
|
133
|
-
});
|
|
188
|
+
main();
|
package/dist/bin/cli.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/bin/cli.ts
|
|
4
|
+
import { parseArgs } from "util";
|
|
5
|
+
import path2 from "path";
|
|
6
|
+
import fs2 from "fs";
|
|
7
|
+
import { createRequire } from "module";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
|
|
10
|
+
// src/builder/index.ts
|
|
11
|
+
import fs from "fs";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import crypto from "crypto";
|
|
14
|
+
async function createUpdatePackage(options) {
|
|
15
|
+
const asar = await import("asar").catch(() => {
|
|
16
|
+
throw new Error('Please install "asar" as a devDependency to use the builder.');
|
|
17
|
+
});
|
|
18
|
+
const {
|
|
19
|
+
outDir,
|
|
20
|
+
updatesDir = path.resolve(process.cwd(), "dist_updates"),
|
|
21
|
+
asarName = "renderer.asar",
|
|
22
|
+
version: explicitVersion,
|
|
23
|
+
packageJsonPath,
|
|
24
|
+
privateKeyPath,
|
|
25
|
+
releaseNotesPath,
|
|
26
|
+
forceUpdate
|
|
27
|
+
} = options;
|
|
28
|
+
if (!fs.existsSync(outDir)) {
|
|
29
|
+
throw new Error(`Output directory not found at ${outDir}`);
|
|
30
|
+
}
|
|
31
|
+
if (!fs.existsSync(updatesDir)) {
|
|
32
|
+
fs.mkdirSync(updatesDir, { recursive: true });
|
|
33
|
+
}
|
|
34
|
+
let version;
|
|
35
|
+
if (explicitVersion) {
|
|
36
|
+
version = explicitVersion;
|
|
37
|
+
} else {
|
|
38
|
+
const pkgPath = packageJsonPath ?? path.resolve(process.cwd(), "package.json");
|
|
39
|
+
if (!fs.existsSync(pkgPath)) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`Cannot resolve version: package.json not found at ${pkgPath}. Please set "version" or "packageJsonPath" in the plugin options.`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
45
|
+
version = pkg.version || "0.0.0";
|
|
46
|
+
}
|
|
47
|
+
const versionDir = path.join(updatesDir, version);
|
|
48
|
+
if (!fs.existsSync(versionDir)) {
|
|
49
|
+
fs.mkdirSync(versionDir, { recursive: true });
|
|
50
|
+
}
|
|
51
|
+
const asarPath = path.join(versionDir, asarName);
|
|
52
|
+
await asar.createPackage(outDir, asarPath);
|
|
53
|
+
const fileBuffer = fs.readFileSync(asarPath);
|
|
54
|
+
const hashSum = crypto.createHash("sha256");
|
|
55
|
+
hashSum.update(fileBuffer);
|
|
56
|
+
const sha256 = hashSum.digest("hex");
|
|
57
|
+
let signature = "";
|
|
58
|
+
if (privateKeyPath && fs.existsSync(privateKeyPath)) {
|
|
59
|
+
const privateKey = fs.readFileSync(privateKeyPath, "utf8");
|
|
60
|
+
const sign = crypto.createSign("RSA-SHA256");
|
|
61
|
+
sign.update(fileBuffer);
|
|
62
|
+
sign.end();
|
|
63
|
+
signature = sign.sign(privateKey, "base64");
|
|
64
|
+
}
|
|
65
|
+
let releaseNotesContent = "No release notes provided.";
|
|
66
|
+
if (releaseNotesPath && fs.existsSync(releaseNotesPath)) {
|
|
67
|
+
releaseNotesContent = fs.readFileSync(releaseNotesPath, "utf-8");
|
|
68
|
+
}
|
|
69
|
+
const updateInfo = {
|
|
70
|
+
version,
|
|
71
|
+
path: `${version}/${asarName}`,
|
|
72
|
+
sha256,
|
|
73
|
+
...signature ? { signature } : {},
|
|
74
|
+
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
75
|
+
releaseNotes: releaseNotesContent,
|
|
76
|
+
...forceUpdate ? { forceUpdate } : {}
|
|
77
|
+
};
|
|
78
|
+
const jsonPath = path.join(updatesDir, "latest.json");
|
|
79
|
+
fs.writeFileSync(jsonPath, JSON.stringify(updateInfo, null, 2));
|
|
80
|
+
console.log(`[RenderUpdater Builder] Successfully created package for v${version}`);
|
|
81
|
+
console.log(`[RenderUpdater Builder] ASAR: ${asarPath}`);
|
|
82
|
+
console.log(`[RenderUpdater Builder] Info: ${jsonPath}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// src/bin/cli.ts
|
|
86
|
+
var require2 = createRequire(import.meta.url);
|
|
87
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
88
|
+
async function main() {
|
|
89
|
+
const args = process.argv.slice(2);
|
|
90
|
+
const options = parseArgs({
|
|
91
|
+
args,
|
|
92
|
+
options: {
|
|
93
|
+
config: { type: "string", short: "c" },
|
|
94
|
+
outDir: { type: "string" },
|
|
95
|
+
version: { type: "string" },
|
|
96
|
+
packageJsonPath: { type: "string" },
|
|
97
|
+
asarName: { type: "string" },
|
|
98
|
+
privateKeyPath: { type: "string" },
|
|
99
|
+
releaseNotesPath: { type: "string" },
|
|
100
|
+
forceUpdate: { type: "string" }
|
|
101
|
+
},
|
|
102
|
+
strict: false
|
|
103
|
+
});
|
|
104
|
+
let configPath = options.values.config;
|
|
105
|
+
const cwd = process.cwd();
|
|
106
|
+
if (!configPath) {
|
|
107
|
+
const defaultConfigs = [
|
|
108
|
+
"updater.config.ts",
|
|
109
|
+
"updater.config.js",
|
|
110
|
+
"updater.config.mjs",
|
|
111
|
+
"updater.config.cjs"
|
|
112
|
+
];
|
|
113
|
+
for (const file of defaultConfigs) {
|
|
114
|
+
if (fs2.existsSync(path2.join(cwd, file))) {
|
|
115
|
+
configPath = file;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
let fileConfig = {};
|
|
121
|
+
if (configPath && typeof configPath === "string") {
|
|
122
|
+
const fullConfigPath = path2.resolve(cwd, configPath);
|
|
123
|
+
if (fs2.existsSync(fullConfigPath)) {
|
|
124
|
+
try {
|
|
125
|
+
const jiti = require2("jiti")(__filename, {
|
|
126
|
+
interopDefault: true,
|
|
127
|
+
cache: false
|
|
128
|
+
});
|
|
129
|
+
const loadedConfig = jiti(fullConfigPath);
|
|
130
|
+
fileConfig = loadedConfig.default || loadedConfig;
|
|
131
|
+
console.log(`[RenderUpdater CLI] Loaded config from ${configPath}`);
|
|
132
|
+
} catch (err) {
|
|
133
|
+
console.error(`[RenderUpdater CLI] Failed to load config from ${configPath}: ${err.message}`);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
console.error(`[RenderUpdater CLI] Config file not found at ${configPath}`);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const finalOptions = {
|
|
142
|
+
...fileConfig
|
|
143
|
+
};
|
|
144
|
+
if (options.values.outDir) finalOptions.outDir = options.values.outDir;
|
|
145
|
+
if (options.values.version) finalOptions.version = options.values.version;
|
|
146
|
+
if (options.values.packageJsonPath) finalOptions.packageJsonPath = options.values.packageJsonPath;
|
|
147
|
+
if (options.values.asarName) finalOptions.asarName = options.values.asarName;
|
|
148
|
+
if (options.values.privateKeyPath) finalOptions.privateKeyPath = options.values.privateKeyPath;
|
|
149
|
+
if (options.values.releaseNotesPath) finalOptions.releaseNotesPath = options.values.releaseNotesPath;
|
|
150
|
+
if (options.values.forceUpdate) {
|
|
151
|
+
finalOptions.forceUpdate = options.values.forceUpdate;
|
|
152
|
+
}
|
|
153
|
+
if (!finalOptions.outDir) {
|
|
154
|
+
console.error("[RenderUpdater CLI] Error: outDir is required. Please specify it in the config file or via --outDir.");
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
try {
|
|
158
|
+
await createUpdatePackage(finalOptions);
|
|
159
|
+
} catch (err) {
|
|
160
|
+
console.error(`[RenderUpdater CLI] Failed to build update package: ${err.message}`);
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
main();
|
package/dist/builder/index.cjs
CHANGED
|
@@ -30,12 +30,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/builder/index.ts
|
|
31
31
|
var builder_exports = {};
|
|
32
32
|
__export(builder_exports, {
|
|
33
|
-
createUpdatePackage: () => createUpdatePackage
|
|
33
|
+
createUpdatePackage: () => createUpdatePackage,
|
|
34
|
+
defineConfig: () => defineConfig
|
|
34
35
|
});
|
|
35
36
|
module.exports = __toCommonJS(builder_exports);
|
|
36
37
|
var import_fs = __toESM(require("fs"), 1);
|
|
37
38
|
var import_path = __toESM(require("path"), 1);
|
|
38
39
|
var import_crypto = __toESM(require("crypto"), 1);
|
|
40
|
+
function defineConfig(config) {
|
|
41
|
+
return config;
|
|
42
|
+
}
|
|
39
43
|
async function createUpdatePackage(options) {
|
|
40
44
|
const asar = await import("asar").catch(() => {
|
|
41
45
|
throw new Error('Please install "asar" as a devDependency to use the builder.');
|
|
@@ -108,5 +112,6 @@ async function createUpdatePackage(options) {
|
|
|
108
112
|
}
|
|
109
113
|
// Annotate the CommonJS export names for ESM import in node:
|
|
110
114
|
0 && (module.exports = {
|
|
111
|
-
createUpdatePackage
|
|
115
|
+
createUpdatePackage,
|
|
116
|
+
defineConfig
|
|
112
117
|
});
|
package/dist/builder/index.d.ts
CHANGED
package/dist/builder/index.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import crypto from "crypto";
|
|
5
|
+
function defineConfig(config) {
|
|
6
|
+
return config;
|
|
7
|
+
}
|
|
5
8
|
async function createUpdatePackage(options) {
|
|
6
9
|
const asar = await import("asar").catch(() => {
|
|
7
10
|
throw new Error('Please install "asar" as a devDependency to use the builder.');
|
|
@@ -73,5 +76,6 @@ async function createUpdatePackage(options) {
|
|
|
73
76
|
console.log(`[RenderUpdater Builder] Info: ${jsonPath}`);
|
|
74
77
|
}
|
|
75
78
|
export {
|
|
76
|
-
createUpdatePackage
|
|
79
|
+
createUpdatePackage,
|
|
80
|
+
defineConfig
|
|
77
81
|
};
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "electron-updater-for-render",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "A lightweight incremental updater for Electron renderer processes",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"electron-updater-for-render": "./dist/bin/cli.js"
|
|
8
|
+
},
|
|
6
9
|
"files": [
|
|
7
10
|
"dist"
|
|
8
11
|
],
|
|
@@ -16,11 +19,6 @@
|
|
|
16
19
|
"types": "./dist/builder/index.d.ts",
|
|
17
20
|
"import": "./dist/builder/index.js",
|
|
18
21
|
"require": "./dist/builder/index.cjs"
|
|
19
|
-
},
|
|
20
|
-
"./vite": {
|
|
21
|
-
"types": "./dist/builder/vite-plugin.d.ts",
|
|
22
|
-
"import": "./dist/builder/vite-plugin.js",
|
|
23
|
-
"require": "./dist/builder/vite-plugin.cjs"
|
|
24
22
|
}
|
|
25
23
|
},
|
|
26
24
|
"scripts": {
|
|
@@ -28,27 +26,23 @@
|
|
|
28
26
|
"dev": "tsup --watch"
|
|
29
27
|
},
|
|
30
28
|
"dependencies": {
|
|
29
|
+
"jiti": "^2.6.1",
|
|
31
30
|
"original-fs": "^1.2.0"
|
|
32
31
|
},
|
|
33
32
|
"peerDependencies": {
|
|
34
33
|
"asar": "^3.2.0",
|
|
35
|
-
"electron": ">=20.0.0"
|
|
36
|
-
"vite": ">=3.0.0"
|
|
34
|
+
"electron": ">=20.0.0"
|
|
37
35
|
},
|
|
38
36
|
"peerDependenciesMeta": {
|
|
39
37
|
"asar": {
|
|
40
38
|
"optional": true
|
|
41
|
-
},
|
|
42
|
-
"vite": {
|
|
43
|
-
"optional": true
|
|
44
39
|
}
|
|
45
40
|
},
|
|
46
41
|
"devDependencies": {
|
|
47
42
|
"@types/node": "^22.0.0",
|
|
48
43
|
"asar": "^3.2.0",
|
|
49
44
|
"tsup": "^8.0.2",
|
|
50
|
-
"typescript": "^5.0.0"
|
|
51
|
-
"vite": "^5.0.0"
|
|
45
|
+
"typescript": "^5.0.0"
|
|
52
46
|
},
|
|
53
47
|
"keywords": [
|
|
54
48
|
"electron",
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
// src/builder/index.ts
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import crypto from "crypto";
|
|
5
|
-
async function createUpdatePackage(options) {
|
|
6
|
-
const asar = await import("asar").catch(() => {
|
|
7
|
-
throw new Error('Please install "asar" as a devDependency to use the builder.');
|
|
8
|
-
});
|
|
9
|
-
const {
|
|
10
|
-
outDir,
|
|
11
|
-
updatesDir = path.resolve(process.cwd(), "dist_updates"),
|
|
12
|
-
asarName = "renderer.asar",
|
|
13
|
-
version: explicitVersion,
|
|
14
|
-
packageJsonPath,
|
|
15
|
-
privateKeyPath,
|
|
16
|
-
releaseNotesPath,
|
|
17
|
-
forceUpdate
|
|
18
|
-
} = options;
|
|
19
|
-
if (!fs.existsSync(outDir)) {
|
|
20
|
-
throw new Error(`Output directory not found at ${outDir}`);
|
|
21
|
-
}
|
|
22
|
-
if (!fs.existsSync(updatesDir)) {
|
|
23
|
-
fs.mkdirSync(updatesDir, { recursive: true });
|
|
24
|
-
}
|
|
25
|
-
let version;
|
|
26
|
-
if (explicitVersion) {
|
|
27
|
-
version = explicitVersion;
|
|
28
|
-
} else {
|
|
29
|
-
const pkgPath = packageJsonPath ?? path.resolve(process.cwd(), "package.json");
|
|
30
|
-
if (!fs.existsSync(pkgPath)) {
|
|
31
|
-
throw new Error(
|
|
32
|
-
`Cannot resolve version: package.json not found at ${pkgPath}. Please set "version" or "packageJsonPath" in the plugin options.`
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
36
|
-
version = pkg.version || "0.0.0";
|
|
37
|
-
}
|
|
38
|
-
const versionDir = path.join(updatesDir, version);
|
|
39
|
-
if (!fs.existsSync(versionDir)) {
|
|
40
|
-
fs.mkdirSync(versionDir, { recursive: true });
|
|
41
|
-
}
|
|
42
|
-
const asarPath = path.join(versionDir, asarName);
|
|
43
|
-
await asar.createPackage(outDir, asarPath);
|
|
44
|
-
const fileBuffer = fs.readFileSync(asarPath);
|
|
45
|
-
const hashSum = crypto.createHash("sha256");
|
|
46
|
-
hashSum.update(fileBuffer);
|
|
47
|
-
const sha256 = hashSum.digest("hex");
|
|
48
|
-
let signature = "";
|
|
49
|
-
if (privateKeyPath && fs.existsSync(privateKeyPath)) {
|
|
50
|
-
const privateKey = fs.readFileSync(privateKeyPath, "utf8");
|
|
51
|
-
const sign = crypto.createSign("RSA-SHA256");
|
|
52
|
-
sign.update(fileBuffer);
|
|
53
|
-
sign.end();
|
|
54
|
-
signature = sign.sign(privateKey, "base64");
|
|
55
|
-
}
|
|
56
|
-
let releaseNotesContent = "No release notes provided.";
|
|
57
|
-
if (releaseNotesPath && fs.existsSync(releaseNotesPath)) {
|
|
58
|
-
releaseNotesContent = fs.readFileSync(releaseNotesPath, "utf-8");
|
|
59
|
-
}
|
|
60
|
-
const updateInfo = {
|
|
61
|
-
version,
|
|
62
|
-
path: `${version}/${asarName}`,
|
|
63
|
-
sha256,
|
|
64
|
-
...signature ? { signature } : {},
|
|
65
|
-
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
66
|
-
releaseNotes: releaseNotesContent,
|
|
67
|
-
...forceUpdate ? { forceUpdate } : {}
|
|
68
|
-
};
|
|
69
|
-
const jsonPath = path.join(updatesDir, "latest.json");
|
|
70
|
-
fs.writeFileSync(jsonPath, JSON.stringify(updateInfo, null, 2));
|
|
71
|
-
console.log(`[RenderUpdater Builder] Successfully created package for v${version}`);
|
|
72
|
-
console.log(`[RenderUpdater Builder] ASAR: ${asarPath}`);
|
|
73
|
-
console.log(`[RenderUpdater Builder] Info: ${jsonPath}`);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// src/builder/vite-plugin.ts
|
|
77
|
-
function electronRenderUpdater(options) {
|
|
78
|
-
return {
|
|
79
|
-
name: "vite-plugin-electron-render-updater",
|
|
80
|
-
apply: "build",
|
|
81
|
-
closeBundle: async () => {
|
|
82
|
-
if (!process.env.ELECTRON_PACK_UPDATE) {
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
console.log("\n[vite-plugin-electron-render-updater] Build finished, packing ASAR...");
|
|
86
|
-
try {
|
|
87
|
-
await createUpdatePackage(options);
|
|
88
|
-
} catch (err) {
|
|
89
|
-
console.error("[vite-plugin-electron-render-updater] Failed to pack ASAR:", err);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
export {
|
|
95
|
-
electronRenderUpdater
|
|
96
|
-
};
|