@grafema/util 0.3.13 → 0.3.15
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.
|
@@ -29,12 +29,15 @@ export declare function findInGrafemaBin(binaryName: string): string | null;
|
|
|
29
29
|
*/
|
|
30
30
|
export declare function downloadBinary(binaryName: string, tag?: string, onProgress?: (msg: string) => void): Promise<string>;
|
|
31
31
|
/**
|
|
32
|
-
* Ensure a binary exists, downloading it if missing
|
|
32
|
+
* Ensure a binary exists and is current, downloading it if missing or stale.
|
|
33
33
|
*
|
|
34
34
|
* This is the main entry point for lazy downloading. Call it before
|
|
35
35
|
* spawning an analyzer binary. Returns the path if found or downloaded,
|
|
36
36
|
* null if the binary can't be obtained.
|
|
37
37
|
*
|
|
38
|
+
* Staleness check: if a binary exists in ~/.grafema/bin/ but its .version
|
|
39
|
+
* file doesn't match the current Grafema release, it is re-downloaded.
|
|
40
|
+
*
|
|
38
41
|
* @param binaryName - e.g. "grafema-analyzer"
|
|
39
42
|
* @param existingPath - path from findBinary() (null = not found locally)
|
|
40
43
|
* @param onProgress - optional callback for download progress
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lazyDownload.d.ts","sourceRoot":"","sources":["../../src/utils/lazyDownload.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"lazyDownload.d.ts","sourceRoot":"","sources":["../../src/utils/lazyDownload.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAyDH;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAGzC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIlE;AA6CD;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,GAAG,CAAC,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GACjC,OAAO,CAAC,MAAM,CAAC,CAmDjB;AAiBD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GACjC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA8BxB"}
|
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
* Asset naming convention: {binary-name}-{platform}
|
|
8
8
|
* Example: grafema-analyzer-darwin-arm64
|
|
9
9
|
*/
|
|
10
|
-
import { existsSync, mkdirSync, chmodSync, renameSync, unlinkSync, createWriteStream } from 'fs';
|
|
10
|
+
import { existsSync, mkdirSync, chmodSync, renameSync, unlinkSync, createWriteStream, readFileSync, writeFileSync } from 'fs';
|
|
11
11
|
import { join } from 'path';
|
|
12
12
|
import { get as httpsGet } from 'https';
|
|
13
13
|
import { getPlatformDir } from './findRfdbBinary.js';
|
|
14
|
+
import { GRAFEMA_VERSION } from '../version.js';
|
|
14
15
|
const GITHUB_REPO = 'Disentinel/grafema';
|
|
15
16
|
/** All analyzer binaries that can be lazy-downloaded. */
|
|
16
17
|
const DOWNLOADABLE_BINARIES = [
|
|
@@ -159,38 +160,70 @@ export async function downloadBinary(binaryName, tag, onProgress) {
|
|
|
159
160
|
// Atomic rename + make executable
|
|
160
161
|
renameSync(tmpPath, targetPath);
|
|
161
162
|
chmodSync(targetPath, 0o755);
|
|
163
|
+
// Record which version was downloaded so we can detect stale binaries
|
|
164
|
+
writeFileSync(`${targetPath}.version`, releaseTag, 'utf-8');
|
|
162
165
|
log(` Installed to ${targetPath}`);
|
|
163
166
|
return targetPath;
|
|
164
167
|
}
|
|
165
168
|
/**
|
|
166
|
-
*
|
|
169
|
+
* Check if a cached binary in ~/.grafema/bin/ is from the current release.
|
|
170
|
+
* Returns true if the binary's .version file matches `binaries-v{GRAFEMA_VERSION}`.
|
|
171
|
+
*/
|
|
172
|
+
function isBinaryCurrentVersion(binaryPath) {
|
|
173
|
+
const versionFile = `${binaryPath}.version`;
|
|
174
|
+
if (!existsSync(versionFile))
|
|
175
|
+
return false;
|
|
176
|
+
try {
|
|
177
|
+
const storedTag = readFileSync(versionFile, 'utf-8').trim();
|
|
178
|
+
return storedTag === `binaries-v${GRAFEMA_VERSION}`;
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Ensure a binary exists and is current, downloading it if missing or stale.
|
|
167
186
|
*
|
|
168
187
|
* This is the main entry point for lazy downloading. Call it before
|
|
169
188
|
* spawning an analyzer binary. Returns the path if found or downloaded,
|
|
170
189
|
* null if the binary can't be obtained.
|
|
171
190
|
*
|
|
191
|
+
* Staleness check: if a binary exists in ~/.grafema/bin/ but its .version
|
|
192
|
+
* file doesn't match the current Grafema release, it is re-downloaded.
|
|
193
|
+
*
|
|
172
194
|
* @param binaryName - e.g. "grafema-analyzer"
|
|
173
195
|
* @param existingPath - path from findBinary() (null = not found locally)
|
|
174
196
|
* @param onProgress - optional callback for download progress
|
|
175
197
|
*/
|
|
176
198
|
export async function ensureBinary(binaryName, existingPath, onProgress) {
|
|
177
|
-
// Already found locally
|
|
199
|
+
// Already found locally (e.g. in platform npm package or PATH)
|
|
178
200
|
if (existingPath)
|
|
179
201
|
return existingPath;
|
|
180
202
|
// Check ~/.grafema/bin/ first (may have been downloaded previously)
|
|
181
203
|
const cached = findInGrafemaBin(binaryName);
|
|
182
|
-
if (cached)
|
|
204
|
+
if (cached && isBinaryCurrentVersion(cached))
|
|
183
205
|
return cached;
|
|
184
206
|
// Not downloadable (e.g. rfdb-server — must be in npm package)
|
|
185
|
-
if (!isDownloadable(binaryName))
|
|
207
|
+
if (!isDownloadable(binaryName)) {
|
|
208
|
+
// If cached exists but is stale and not downloadable, return it anyway
|
|
209
|
+
if (cached)
|
|
210
|
+
return cached;
|
|
186
211
|
return null;
|
|
187
|
-
|
|
212
|
+
}
|
|
213
|
+
// Download (missing or stale)
|
|
214
|
+
const log = onProgress || (() => { });
|
|
215
|
+
if (cached) {
|
|
216
|
+
log(`Updating ${binaryName} to binaries-v${GRAFEMA_VERSION}...`);
|
|
217
|
+
}
|
|
188
218
|
try {
|
|
189
|
-
return await downloadBinary(binaryName,
|
|
219
|
+
return await downloadBinary(binaryName, `binaries-v${GRAFEMA_VERSION}`, onProgress);
|
|
190
220
|
}
|
|
191
221
|
catch (err) {
|
|
192
222
|
const msg = err instanceof Error ? err.message : String(err);
|
|
193
223
|
(onProgress || console.error)(`Failed to download ${binaryName}: ${msg}`);
|
|
224
|
+
// Fall back to stale binary if download fails
|
|
225
|
+
if (cached)
|
|
226
|
+
return cached;
|
|
194
227
|
return null;
|
|
195
228
|
}
|
|
196
229
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lazyDownload.js","sourceRoot":"","sources":["../../src/utils/lazyDownload.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"lazyDownload.js","sourceRoot":"","sources":["../../src/utils/lazyDownload.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grafema/util",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.15",
|
|
4
4
|
"description": "Query, config, and guarantee utilities for Grafema",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"ajv": "^8.17.1",
|
|
36
36
|
"minimatch": "^10.1.1",
|
|
37
37
|
"yaml": "^2.8.2",
|
|
38
|
-
"@grafema/rfdb-client": "0.3.
|
|
39
|
-
"@grafema/types": "0.3.
|
|
38
|
+
"@grafema/rfdb-client": "0.3.15",
|
|
39
|
+
"@grafema/types": "0.3.15"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/node": "^25.0.8",
|
|
@@ -8,11 +8,12 @@
|
|
|
8
8
|
* Example: grafema-analyzer-darwin-arm64
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { existsSync, mkdirSync, chmodSync, renameSync, unlinkSync, createWriteStream } from 'fs';
|
|
11
|
+
import { existsSync, mkdirSync, chmodSync, renameSync, unlinkSync, createWriteStream, readFileSync, writeFileSync } from 'fs';
|
|
12
12
|
import { join } from 'path';
|
|
13
13
|
import { get as httpsGet } from 'https';
|
|
14
14
|
import type { IncomingMessage } from 'http';
|
|
15
15
|
import { getPlatformDir } from './findRfdbBinary.js';
|
|
16
|
+
import { GRAFEMA_VERSION } from '../version.js';
|
|
16
17
|
|
|
17
18
|
const GITHUB_REPO = 'Disentinel/grafema';
|
|
18
19
|
|
|
@@ -187,17 +188,38 @@ export async function downloadBinary(
|
|
|
187
188
|
renameSync(tmpPath, targetPath);
|
|
188
189
|
chmodSync(targetPath, 0o755);
|
|
189
190
|
|
|
191
|
+
// Record which version was downloaded so we can detect stale binaries
|
|
192
|
+
writeFileSync(`${targetPath}.version`, releaseTag, 'utf-8');
|
|
193
|
+
|
|
190
194
|
log(` Installed to ${targetPath}`);
|
|
191
195
|
return targetPath;
|
|
192
196
|
}
|
|
193
197
|
|
|
194
198
|
/**
|
|
195
|
-
*
|
|
199
|
+
* Check if a cached binary in ~/.grafema/bin/ is from the current release.
|
|
200
|
+
* Returns true if the binary's .version file matches `binaries-v{GRAFEMA_VERSION}`.
|
|
201
|
+
*/
|
|
202
|
+
function isBinaryCurrentVersion(binaryPath: string): boolean {
|
|
203
|
+
const versionFile = `${binaryPath}.version`;
|
|
204
|
+
if (!existsSync(versionFile)) return false;
|
|
205
|
+
try {
|
|
206
|
+
const storedTag = readFileSync(versionFile, 'utf-8').trim();
|
|
207
|
+
return storedTag === `binaries-v${GRAFEMA_VERSION}`;
|
|
208
|
+
} catch {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Ensure a binary exists and is current, downloading it if missing or stale.
|
|
196
215
|
*
|
|
197
216
|
* This is the main entry point for lazy downloading. Call it before
|
|
198
217
|
* spawning an analyzer binary. Returns the path if found or downloaded,
|
|
199
218
|
* null if the binary can't be obtained.
|
|
200
219
|
*
|
|
220
|
+
* Staleness check: if a binary exists in ~/.grafema/bin/ but its .version
|
|
221
|
+
* file doesn't match the current Grafema release, it is re-downloaded.
|
|
222
|
+
*
|
|
201
223
|
* @param binaryName - e.g. "grafema-analyzer"
|
|
202
224
|
* @param existingPath - path from findBinary() (null = not found locally)
|
|
203
225
|
* @param onProgress - optional callback for download progress
|
|
@@ -207,22 +229,33 @@ export async function ensureBinary(
|
|
|
207
229
|
existingPath: string | null,
|
|
208
230
|
onProgress?: (msg: string) => void,
|
|
209
231
|
): Promise<string | null> {
|
|
210
|
-
// Already found locally
|
|
232
|
+
// Already found locally (e.g. in platform npm package or PATH)
|
|
211
233
|
if (existingPath) return existingPath;
|
|
212
234
|
|
|
213
235
|
// Check ~/.grafema/bin/ first (may have been downloaded previously)
|
|
214
236
|
const cached = findInGrafemaBin(binaryName);
|
|
215
|
-
if (cached) return cached;
|
|
237
|
+
if (cached && isBinaryCurrentVersion(cached)) return cached;
|
|
216
238
|
|
|
217
239
|
// Not downloadable (e.g. rfdb-server — must be in npm package)
|
|
218
|
-
if (!isDownloadable(binaryName))
|
|
240
|
+
if (!isDownloadable(binaryName)) {
|
|
241
|
+
// If cached exists but is stale and not downloadable, return it anyway
|
|
242
|
+
if (cached) return cached;
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Download (missing or stale)
|
|
247
|
+
const log = onProgress || (() => {});
|
|
248
|
+
if (cached) {
|
|
249
|
+
log(`Updating ${binaryName} to binaries-v${GRAFEMA_VERSION}...`);
|
|
250
|
+
}
|
|
219
251
|
|
|
220
|
-
// Download
|
|
221
252
|
try {
|
|
222
|
-
return await downloadBinary(binaryName,
|
|
253
|
+
return await downloadBinary(binaryName, `binaries-v${GRAFEMA_VERSION}`, onProgress);
|
|
223
254
|
} catch (err) {
|
|
224
255
|
const msg = err instanceof Error ? err.message : String(err);
|
|
225
256
|
(onProgress || console.error)(`Failed to download ${binaryName}: ${msg}`);
|
|
257
|
+
// Fall back to stale binary if download fails
|
|
258
|
+
if (cached) return cached;
|
|
226
259
|
return null;
|
|
227
260
|
}
|
|
228
261
|
}
|