gloomberb 0.3.1 → 0.3.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/src/updater.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { writeFileSync, renameSync, unlinkSync, chmodSync, realpathSync } from "fs";
2
2
  import { basename } from "path";
3
+ import { gunzipSync } from "zlib";
3
4
 
4
5
  const REPO = "vincelwt/gloomberb";
5
6
  const API_URL = `https://api.github.com/repos/${REPO}/releases/latest`;
@@ -10,6 +11,7 @@ export interface ReleaseInfo {
10
11
  downloadUrl: string;
11
12
  publishedAt: string;
12
13
  updateAction: UpdateAction;
14
+ compressed?: boolean;
13
15
  }
14
16
 
15
17
  export interface UpdateProgress {
@@ -22,6 +24,12 @@ export type UpdateAction =
22
24
  | { kind: "self" }
23
25
  | { kind: "manual"; command: string };
24
26
 
27
+ export type UpdateCheckResult =
28
+ | { kind: "available"; release: ReleaseInfo }
29
+ | { kind: "current" }
30
+ | { kind: "disabled" }
31
+ | { kind: "error"; error: string };
32
+
25
33
  function compareSemver(a: string, b: string): number {
26
34
  const pa = a.split(".").map(Number);
27
35
  const pb = b.split(".").map(Number);
@@ -32,13 +40,30 @@ function compareSemver(a: string, b: string): number {
32
40
  return 0;
33
41
  }
34
42
 
35
- function getAssetName(): string {
43
+ function getAssetBaseName(): string {
36
44
  const os = process.platform === "darwin" ? "darwin" : "linux";
37
45
  // macOS x64 uses arm64 binary (runs via Rosetta 2)
38
46
  const arch = os === "darwin" || process.arch === "arm64" ? "arm64" : "x64";
39
47
  return `gloomberb-${os}-${arch}`;
40
48
  }
41
49
 
50
+ function resolveReleaseAsset(
51
+ assets: { name: string; browser_download_url: string }[],
52
+ ): { name: string; browser_download_url: string; compressed: boolean } | null {
53
+ const assetBaseName = getAssetBaseName();
54
+ const gzAsset = assets.find((asset) => asset.name === `${assetBaseName}.gz`);
55
+ if (gzAsset) {
56
+ return { ...gzAsset, compressed: true };
57
+ }
58
+
59
+ const rawAsset = assets.find((asset) => asset.name === assetBaseName);
60
+ if (rawAsset) {
61
+ return { ...rawAsset, compressed: false };
62
+ }
63
+
64
+ return null;
65
+ }
66
+
42
67
  function normalizePath(value: string): string {
43
68
  return value.replace(/\\/g, "/").toLowerCase();
44
69
  }
@@ -123,23 +148,27 @@ export function canSelfUpdate(release: Pick<ReleaseInfo, "updateAction"> | null
123
148
  return release?.updateAction.kind === "self";
124
149
  }
125
150
 
126
- export async function checkForUpdate(
151
+ export async function checkForUpdateDetailed(
127
152
  currentVersion: string,
128
- ): Promise<ReleaseInfo | null> {
153
+ ): Promise<UpdateCheckResult> {
129
154
  const updateAction = detectUpdateAction();
130
- if (!updateAction) return null;
155
+ if (!updateAction) {
156
+ return { kind: "disabled" };
157
+ }
131
158
 
159
+ let timeout: ReturnType<typeof setTimeout> | undefined;
132
160
  try {
133
161
  const controller = new AbortController();
134
- const timeout = setTimeout(() => controller.abort(), 5000);
162
+ timeout = setTimeout(() => controller.abort(), 5000);
135
163
 
136
164
  const res = await fetch(API_URL, {
137
165
  signal: controller.signal,
138
166
  headers: { Accept: "application/vnd.github+json" },
139
167
  });
140
- clearTimeout(timeout);
141
168
 
142
- if (!res.ok) return null;
169
+ if (!res.ok) {
170
+ return { kind: "error", error: `GitHub returned ${res.status}` };
171
+ }
143
172
 
144
173
  const data = (await res.json()) as {
145
174
  tag_name: string;
@@ -148,24 +177,49 @@ export async function checkForUpdate(
148
177
  };
149
178
 
150
179
  const version = data.tag_name.replace(/^v/, "");
151
- if (compareSemver(version, currentVersion) <= 0) return null;
180
+ if (compareSemver(version, currentVersion) <= 0) {
181
+ return { kind: "current" };
182
+ }
152
183
 
153
- const assetName = getAssetName();
154
- const asset = data.assets.find((a) => a.name === assetName);
155
- if (!asset) return null;
184
+ const asset = resolveReleaseAsset(data.assets);
185
+ if (!asset) {
186
+ return {
187
+ kind: "error",
188
+ error: `No compatible release asset found for ${getAssetBaseName()}`,
189
+ };
190
+ }
156
191
 
157
192
  return {
158
- version,
159
- tagName: data.tag_name,
160
- downloadUrl: asset.browser_download_url,
161
- publishedAt: data.published_at,
162
- updateAction,
193
+ kind: "available",
194
+ release: {
195
+ version,
196
+ tagName: data.tag_name,
197
+ downloadUrl: asset.browser_download_url,
198
+ publishedAt: data.published_at,
199
+ updateAction,
200
+ compressed: asset.compressed,
201
+ },
163
202
  };
164
- } catch {
165
- return null;
203
+ } catch (error: unknown) {
204
+ if (error instanceof Error && error.name === "AbortError") {
205
+ return { kind: "error", error: "Update check timed out" };
206
+ }
207
+ return {
208
+ kind: "error",
209
+ error: error instanceof Error ? error.message : "Update check failed",
210
+ };
211
+ } finally {
212
+ if (timeout) clearTimeout(timeout);
166
213
  }
167
214
  }
168
215
 
216
+ export async function checkForUpdate(
217
+ currentVersion: string,
218
+ ): Promise<ReleaseInfo | null> {
219
+ const result = await checkForUpdateDetailed(currentVersion);
220
+ return result.kind === "available" ? result.release : null;
221
+ }
222
+
169
223
  export async function performUpdate(
170
224
  release: ReleaseInfo,
171
225
  onProgress: (p: UpdateProgress) => void,
@@ -219,7 +273,9 @@ export async function performUpdate(
219
273
  // Write to temp file
220
274
  const blob = new Blob(chunks);
221
275
  const buffer = await blob.arrayBuffer();
222
- writeFileSync(updatePath, Buffer.from(buffer));
276
+ const downloaded = Buffer.from(buffer);
277
+ const nextBinary = release.compressed ? gunzipSync(downloaded) : downloaded;
278
+ writeFileSync(updatePath, nextBinary);
223
279
  chmodSync(updatePath, 0o755);
224
280
 
225
281
  // Swap binaries
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = "0.3.1";
1
+ export const VERSION = "0.3.2";