electron-incremental-update 0.1.1 → 0.1.2

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.md CHANGED
@@ -47,7 +47,7 @@ const SIGNATURE_PUB = '' // auto generate RSA public key when start app
47
47
 
48
48
  const updater = createUpdater({
49
49
  SIGNATURE_PUB,
50
- githubRepository: repository,
50
+ repository,
51
51
  productName: name,
52
52
  })
53
53
  initApp(name, updater)
package/dist/index.cjs CHANGED
@@ -91,14 +91,20 @@ var import_node_https = __toESM(require("https"), 1);
91
91
  var import_electron2 = require("electron");
92
92
  function createUpdater({
93
93
  SIGNATURE_PUB,
94
- githubRepository,
94
+ repository,
95
95
  productName,
96
- releaseCdnPrefix: _release,
97
- updateJsonURL: _update
96
+ releaseAsarURL: _release,
97
+ updateJsonURL: _update,
98
+ userAgent,
99
+ extraHeader
98
100
  }) {
99
101
  const updater = new import_node_events.EventEmitter();
100
102
  async function download(url, format) {
101
- const ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36";
103
+ const ua = userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36";
104
+ const commonHeader = {
105
+ UserAgent: ua,
106
+ ...extraHeader
107
+ };
102
108
  return await new Promise((resolve2, reject) => {
103
109
  import_node_https.default.get(url, (res) => {
104
110
  if (format === "json") {
@@ -106,7 +112,7 @@ function createUpdater({
106
112
  res.setEncoding("utf8");
107
113
  res.headers = {
108
114
  Accept: "application/json",
109
- UserAgent: ua
115
+ ...commonHeader
110
116
  };
111
117
  res.on("data", (chunk) => data += chunk);
112
118
  res.on("end", () => {
@@ -116,7 +122,7 @@ function createUpdater({
116
122
  let data = [];
117
123
  res.headers = {
118
124
  Accept: "application/octet-stream",
119
- UserAgent: ua
125
+ ...commonHeader
120
126
  };
121
127
  res.on("data", (chunk) => {
122
128
  updater.emit("downloading", chunk.length);
@@ -164,17 +170,21 @@ function createUpdater({
164
170
  return import_electron2.app.isPackaged && parseVersion(import_electron2.app.getVersion()) < parseVersion(version);
165
171
  }
166
172
  async function checkUpdate(option) {
167
- const { releaseCdnPrefix, updateJsonURL } = option || {};
173
+ let {
174
+ updateJsonURL = _update,
175
+ releaseAsarURL = _release
176
+ } = option || {};
177
+ if ((!updateJsonURL || !releaseAsarURL) && !repository) {
178
+ throw new Error("updateJsonURL or releaseAsarURL are not set");
179
+ }
180
+ updateJsonURL ??= `${repository}/version.json`;
181
+ releaseAsarURL ??= `${repository}/releases/download/latest/${productName}.asar.gz`;
168
182
  const gzipPath = `../${productName}.asar.gz`;
169
183
  const tmpFile = gzipPath.replace(".asar.gz", ".tmp.gz");
170
- const base = githubRepository.replace("https://github.com", "");
171
- const updateJSONUrl = updateJsonURL ?? _update ?? `https://cdn.jsdelivr.net/gh/${base}/version.json`;
172
- const prefix = releaseCdnPrefix ?? _release;
173
- const downloadUrl = `${prefix ? `${prefix}/${base}` : githubRepository}/releases/download/latest/${productName}.asar.gz`;
174
184
  if ((0, import_node_fs2.existsSync)(tmpFile)) {
175
185
  await (0, import_promises.rm)(tmpFile);
176
186
  }
177
- const json = await download(updateJSONUrl, "json");
187
+ const json = await download(updateJsonURL, "json");
178
188
  if (!json) {
179
189
  throw new Error("fetch update json failed");
180
190
  }
@@ -183,12 +193,11 @@ function createUpdater({
183
193
  version,
184
194
  size
185
195
  } = json;
186
- console.log(version, size, signature);
187
196
  if (!needUpdate(version)) {
188
197
  return "unavailable";
189
198
  }
190
199
  updater.emit("downloadStart", size);
191
- const buffer = await download(downloadUrl, "buffer");
200
+ const buffer = await download(releaseAsarURL, "buffer");
192
201
  if (!verify(buffer, signature)) {
193
202
  throw new Error("file broken, invalid signature!");
194
203
  }
package/dist/index.d.ts CHANGED
@@ -8,9 +8,19 @@ type UpdateEvents = {
8
8
  donwnloadError: [error: unknown];
9
9
  };
10
10
  type MaybeArray<T> = T extends undefined | null | never ? [] : T extends any[] ? T['length'] extends 1 ? [data: T[0]] : T : [data: T];
11
- interface CheckUpdateOption {
11
+ interface UpdateOption {
12
+ /**
13
+ * URL of version info json
14
+ * @default `${repository}/version.json`
15
+ * @throws if `updateJsonURL` and `repository` are all not set
16
+ */
12
17
  updateJsonURL?: string;
13
- releaseCdnPrefix?: string;
18
+ /**
19
+ * URL of release asar.gz
20
+ * @default `${repository}/releases/download/latest/${productName}.asar.gz`
21
+ * @throws if `releaseAsarURL` and `repository` are all not set
22
+ */
23
+ releaseAsarURL?: string;
14
24
  }
15
25
  interface TypedUpdater<T extends Record<string | symbol, MaybeArray<any>>, Event extends Exclude<keyof T, number> = Exclude<keyof T, number>> {
16
26
  removeAllListeners<E extends Event>(event?: E): this;
@@ -20,15 +30,52 @@ interface TypedUpdater<T extends Record<string | symbol, MaybeArray<any>>, Event
20
30
  once<E extends Event>(eventName: E, listener: (...args: MaybeArray<T[E]>) => void): this;
21
31
  emit<E extends Event>(eventName: E, ...args: MaybeArray<T[E]>): boolean;
22
32
  off<E extends Event>(eventName: E, listener: (...args: MaybeArray<T[E]>) => void): this;
23
- checkUpdate(options?: CheckUpdateOption): Promise<void>;
33
+ checkUpdate(options?: UpdateOption): Promise<void>;
24
34
  }
25
35
  type Updater = TypedUpdater<UpdateEvents>;
26
- interface Options extends CheckUpdateOption {
36
+ interface Options extends UpdateOption {
37
+ /**
38
+ * public key of signature
39
+ *
40
+ * it will be auto generated by plugin
41
+ * @example
42
+ * ```ts
43
+ * // auto filled by plugin
44
+ * const SIGNATURE_PUB = ''
45
+ *
46
+ * const updater = createUpdater({
47
+ * SIGNATURE_PUB,
48
+ * ...
49
+ * })
50
+ * ```
51
+ */
27
52
  SIGNATURE_PUB: string;
53
+ /**
54
+ * product name
55
+ *
56
+ * you can use the `name` in package.json
57
+ */
28
58
  productName: string;
29
- githubRepository: string;
59
+ /**
60
+ * repository url, e.g. `https://github.com/electron/electron`
61
+ *
62
+ * you can use the `repository` in package.json
63
+ *
64
+ * if `updateJsonURL` or `releaseAsarURL` are absent,
65
+ * `repository` will be used to determine the url
66
+ */
67
+ repository?: string;
68
+ /**
69
+ * download user agent
70
+ * @default 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36'
71
+ */
72
+ userAgent?: string;
73
+ /**
74
+ * extra download header, `accept` and `user-agent` is set by default
75
+ */
76
+ extraHeader?: Record<string, string>;
30
77
  }
31
- declare function createUpdater({ SIGNATURE_PUB, githubRepository, productName, releaseCdnPrefix: _release, updateJsonURL: _update, }: Options): Updater;
78
+ declare function createUpdater({ SIGNATURE_PUB, repository, productName, releaseAsarURL: _release, updateJsonURL: _update, userAgent, extraHeader, }: Options): Updater;
32
79
 
33
80
  declare function getAppAsarPath(name: string): string;
34
81
  declare function getElectronVersion(): string;
package/dist/index.mjs CHANGED
@@ -55,14 +55,20 @@ import https from "node:https";
55
55
  import { app as app2 } from "electron";
56
56
  function createUpdater({
57
57
  SIGNATURE_PUB,
58
- githubRepository,
58
+ repository,
59
59
  productName,
60
- releaseCdnPrefix: _release,
61
- updateJsonURL: _update
60
+ releaseAsarURL: _release,
61
+ updateJsonURL: _update,
62
+ userAgent,
63
+ extraHeader
62
64
  }) {
63
65
  const updater = new EventEmitter();
64
66
  async function download(url, format) {
65
- const ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36";
67
+ const ua = userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36";
68
+ const commonHeader = {
69
+ UserAgent: ua,
70
+ ...extraHeader
71
+ };
66
72
  return await new Promise((resolve2, reject) => {
67
73
  https.get(url, (res) => {
68
74
  if (format === "json") {
@@ -70,7 +76,7 @@ function createUpdater({
70
76
  res.setEncoding("utf8");
71
77
  res.headers = {
72
78
  Accept: "application/json",
73
- UserAgent: ua
79
+ ...commonHeader
74
80
  };
75
81
  res.on("data", (chunk) => data += chunk);
76
82
  res.on("end", () => {
@@ -80,7 +86,7 @@ function createUpdater({
80
86
  let data = [];
81
87
  res.headers = {
82
88
  Accept: "application/octet-stream",
83
- UserAgent: ua
89
+ ...commonHeader
84
90
  };
85
91
  res.on("data", (chunk) => {
86
92
  updater.emit("downloading", chunk.length);
@@ -128,17 +134,21 @@ function createUpdater({
128
134
  return app2.isPackaged && parseVersion(app2.getVersion()) < parseVersion(version);
129
135
  }
130
136
  async function checkUpdate(option) {
131
- const { releaseCdnPrefix, updateJsonURL } = option || {};
137
+ let {
138
+ updateJsonURL = _update,
139
+ releaseAsarURL = _release
140
+ } = option || {};
141
+ if ((!updateJsonURL || !releaseAsarURL) && !repository) {
142
+ throw new Error("updateJsonURL or releaseAsarURL are not set");
143
+ }
144
+ updateJsonURL ??= `${repository}/version.json`;
145
+ releaseAsarURL ??= `${repository}/releases/download/latest/${productName}.asar.gz`;
132
146
  const gzipPath = `../${productName}.asar.gz`;
133
147
  const tmpFile = gzipPath.replace(".asar.gz", ".tmp.gz");
134
- const base = githubRepository.replace("https://github.com", "");
135
- const updateJSONUrl = updateJsonURL ?? _update ?? `https://cdn.jsdelivr.net/gh/${base}/version.json`;
136
- const prefix = releaseCdnPrefix ?? _release;
137
- const downloadUrl = `${prefix ? `${prefix}/${base}` : githubRepository}/releases/download/latest/${productName}.asar.gz`;
138
148
  if (existsSync(tmpFile)) {
139
149
  await rm(tmpFile);
140
150
  }
141
- const json = await download(updateJSONUrl, "json");
151
+ const json = await download(updateJsonURL, "json");
142
152
  if (!json) {
143
153
  throw new Error("fetch update json failed");
144
154
  }
@@ -147,12 +157,11 @@ function createUpdater({
147
157
  version,
148
158
  size
149
159
  } = json;
150
- console.log(version, size, signature);
151
160
  if (!needUpdate(version)) {
152
161
  return "unavailable";
153
162
  }
154
163
  updater.emit("downloadStart", size);
155
- const buffer = await download(downloadUrl, "buffer");
164
+ const buffer = await download(releaseAsarURL, "buffer");
156
165
  if (!verify(buffer, signature)) {
157
166
  throw new Error("file broken, invalid signature!");
158
167
  }
package/dist/vite.cjs CHANGED
@@ -140,7 +140,8 @@ async function buildAsar({
140
140
  asarOutputPath,
141
141
  privateKeyPath,
142
142
  electronDistPath,
143
- rendererDistPath
143
+ rendererDistPath,
144
+ versionPath
144
145
  }) {
145
146
  await (0, import_promises2.rename)(rendererDistPath, `${electronDistPath}/renderer`);
146
147
  await (0, import_promises2.writeFile)(`${electronDistPath}/version`, version);
@@ -151,7 +152,7 @@ async function buildAsar({
151
152
  await gzipFile(asarOutputPath);
152
153
  const buffer = await (0, import_promises2.readFile)(`${asarOutputPath}.gz`);
153
154
  const signature = generateSignature(buffer, await (0, import_promises2.readFile)(privateKeyPath, "utf-8"));
154
- await (0, import_promises2.writeFile)("version.json", JSON.stringify({
155
+ await (0, import_promises2.writeFile)(versionPath, JSON.stringify({
155
156
  signature,
156
157
  version,
157
158
  size: buffer.length
@@ -166,7 +167,8 @@ function parseOptions(options) {
166
167
  entryOutputPath = "app.js",
167
168
  asarOutputPath = `release/${productName}.asar`,
168
169
  electronDistPath = "dist-electron",
169
- rendererDistPath = "dist"
170
+ rendererDistPath = "dist",
171
+ versionPath = "version.json"
170
172
  } = paths;
171
173
  const {
172
174
  privateKeyPath = "public/private.pem",
@@ -175,11 +177,11 @@ function parseOptions(options) {
175
177
  } = keys;
176
178
  const buildAsarOption = {
177
179
  version,
178
- productName,
179
180
  asarOutputPath,
180
181
  privateKeyPath,
181
182
  electronDistPath,
182
- rendererDistPath
183
+ rendererDistPath,
184
+ versionPath
183
185
  };
184
186
  const buildEntryOption = {
185
187
  privateKeyPath,
package/dist/vite.d.ts CHANGED
@@ -47,6 +47,11 @@ type Options = {
47
47
  * @default `dist`
48
48
  */
49
49
  rendererDistPath?: string;
50
+ /**
51
+ * Path to version info output
52
+ * @default `version.json`
53
+ */
54
+ versionPath?: string;
50
55
  };
51
56
  keys?: {
52
57
  /**
package/dist/vite.mjs CHANGED
@@ -108,7 +108,8 @@ async function buildAsar({
108
108
  asarOutputPath,
109
109
  privateKeyPath,
110
110
  electronDistPath,
111
- rendererDistPath
111
+ rendererDistPath,
112
+ versionPath
112
113
  }) {
113
114
  await rename(rendererDistPath, `${electronDistPath}/renderer`);
114
115
  await writeFile2(`${electronDistPath}/version`, version);
@@ -119,7 +120,7 @@ async function buildAsar({
119
120
  await gzipFile(asarOutputPath);
120
121
  const buffer = await readFile2(`${asarOutputPath}.gz`);
121
122
  const signature = generateSignature(buffer, await readFile2(privateKeyPath, "utf-8"));
122
- await writeFile2("version.json", JSON.stringify({
123
+ await writeFile2(versionPath, JSON.stringify({
123
124
  signature,
124
125
  version,
125
126
  size: buffer.length
@@ -134,7 +135,8 @@ function parseOptions(options) {
134
135
  entryOutputPath = "app.js",
135
136
  asarOutputPath = `release/${productName}.asar`,
136
137
  electronDistPath = "dist-electron",
137
- rendererDistPath = "dist"
138
+ rendererDistPath = "dist",
139
+ versionPath = "version.json"
138
140
  } = paths;
139
141
  const {
140
142
  privateKeyPath = "public/private.pem",
@@ -143,11 +145,11 @@ function parseOptions(options) {
143
145
  } = keys;
144
146
  const buildAsarOption = {
145
147
  version,
146
- productName,
147
148
  asarOutputPath,
148
149
  privateKeyPath,
149
150
  electronDistPath,
150
- rendererDistPath
151
+ rendererDistPath,
152
+ versionPath
151
153
  };
152
154
  const buildEntryOption = {
153
155
  privateKeyPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electron-incremental-update",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "electron incremental update tools, powered by vite",
5
5
  "scripts": {
6
6
  "build": "tsup",