@grafema/util 0.3.14 → 0.3.16
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;AAuCD;;;;;;;;;;;;;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,92 @@ 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
|
+
* Extract semver from a binaries tag: "binaries-v0.3.14" → "0.3.14"
|
|
170
|
+
*/
|
|
171
|
+
function versionFromTag(tag) {
|
|
172
|
+
return tag.replace(/^binaries-v/, '');
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Compare two semver strings. Returns true if a >= b.
|
|
176
|
+
* Simple numeric comparison of major.minor.patch.
|
|
177
|
+
*/
|
|
178
|
+
function semverGte(a, b) {
|
|
179
|
+
const pa = a.split('-')[0].split('.').map(Number);
|
|
180
|
+
const pb = b.split('-')[0].split('.').map(Number);
|
|
181
|
+
for (let i = 0; i < 3; i++) {
|
|
182
|
+
if ((pa[i] || 0) > (pb[i] || 0))
|
|
183
|
+
return true;
|
|
184
|
+
if ((pa[i] || 0) < (pb[i] || 0))
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
return true; // equal
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Check if a cached binary in ~/.grafema/bin/ is from a release >= current version.
|
|
191
|
+
* The .version file stores the release tag used for download (e.g. "binaries-v0.3.14").
|
|
192
|
+
*/
|
|
193
|
+
function isBinaryCurrentVersion(binaryPath) {
|
|
194
|
+
const versionFile = `${binaryPath}.version`;
|
|
195
|
+
if (!existsSync(versionFile))
|
|
196
|
+
return false;
|
|
197
|
+
try {
|
|
198
|
+
const storedTag = readFileSync(versionFile, 'utf-8').trim();
|
|
199
|
+
const storedVersion = versionFromTag(storedTag);
|
|
200
|
+
return semverGte(storedVersion, GRAFEMA_VERSION);
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Ensure a binary exists and is current, downloading it if missing or stale.
|
|
167
208
|
*
|
|
168
209
|
* This is the main entry point for lazy downloading. Call it before
|
|
169
210
|
* spawning an analyzer binary. Returns the path if found or downloaded,
|
|
170
211
|
* null if the binary can't be obtained.
|
|
171
212
|
*
|
|
213
|
+
* Staleness check: if a binary exists in ~/.grafema/bin/ but its .version
|
|
214
|
+
* file doesn't match the current Grafema release, it is re-downloaded.
|
|
215
|
+
*
|
|
172
216
|
* @param binaryName - e.g. "grafema-analyzer"
|
|
173
217
|
* @param existingPath - path from findBinary() (null = not found locally)
|
|
174
218
|
* @param onProgress - optional callback for download progress
|
|
175
219
|
*/
|
|
176
220
|
export async function ensureBinary(binaryName, existingPath, onProgress) {
|
|
177
|
-
// Already found locally
|
|
221
|
+
// Already found locally (e.g. in platform npm package or PATH)
|
|
178
222
|
if (existingPath)
|
|
179
223
|
return existingPath;
|
|
180
224
|
// Check ~/.grafema/bin/ first (may have been downloaded previously)
|
|
181
225
|
const cached = findInGrafemaBin(binaryName);
|
|
182
|
-
if (cached)
|
|
226
|
+
if (cached && isBinaryCurrentVersion(cached))
|
|
183
227
|
return cached;
|
|
184
228
|
// Not downloadable (e.g. rfdb-server — must be in npm package)
|
|
185
|
-
if (!isDownloadable(binaryName))
|
|
229
|
+
if (!isDownloadable(binaryName)) {
|
|
230
|
+
// If cached exists but is stale and not downloadable, return it anyway
|
|
231
|
+
if (cached)
|
|
232
|
+
return cached;
|
|
186
233
|
return null;
|
|
187
|
-
|
|
234
|
+
}
|
|
235
|
+
// Download (missing or stale) — auto-detect latest binaries-v* release tag
|
|
236
|
+
const log = onProgress || (() => { });
|
|
237
|
+
if (cached) {
|
|
238
|
+
log(`Updating ${binaryName} (stale binary detected)...`);
|
|
239
|
+
}
|
|
188
240
|
try {
|
|
189
241
|
return await downloadBinary(binaryName, undefined, onProgress);
|
|
190
242
|
}
|
|
191
243
|
catch (err) {
|
|
192
244
|
const msg = err instanceof Error ? err.message : String(err);
|
|
193
245
|
(onProgress || console.error)(`Failed to download ${binaryName}: ${msg}`);
|
|
246
|
+
// Fall back to stale binary if download fails
|
|
247
|
+
if (cached)
|
|
248
|
+
return cached;
|
|
194
249
|
return null;
|
|
195
250
|
}
|
|
196
251
|
}
|
|
@@ -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.16",
|
|
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/
|
|
39
|
-
"@grafema/
|
|
38
|
+
"@grafema/rfdb-client": "0.3.16",
|
|
39
|
+
"@grafema/types": "0.3.16"
|
|
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,60 @@ 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
|
+
* Extract semver from a binaries tag: "binaries-v0.3.14" → "0.3.14"
|
|
200
|
+
*/
|
|
201
|
+
function versionFromTag(tag: string): string {
|
|
202
|
+
return tag.replace(/^binaries-v/, '');
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Compare two semver strings. Returns true if a >= b.
|
|
207
|
+
* Simple numeric comparison of major.minor.patch.
|
|
208
|
+
*/
|
|
209
|
+
function semverGte(a: string, b: string): boolean {
|
|
210
|
+
const pa = a.split('-')[0].split('.').map(Number);
|
|
211
|
+
const pb = b.split('-')[0].split('.').map(Number);
|
|
212
|
+
for (let i = 0; i < 3; i++) {
|
|
213
|
+
if ((pa[i] || 0) > (pb[i] || 0)) return true;
|
|
214
|
+
if ((pa[i] || 0) < (pb[i] || 0)) return false;
|
|
215
|
+
}
|
|
216
|
+
return true; // equal
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Check if a cached binary in ~/.grafema/bin/ is from a release >= current version.
|
|
221
|
+
* The .version file stores the release tag used for download (e.g. "binaries-v0.3.14").
|
|
222
|
+
*/
|
|
223
|
+
function isBinaryCurrentVersion(binaryPath: string): boolean {
|
|
224
|
+
const versionFile = `${binaryPath}.version`;
|
|
225
|
+
if (!existsSync(versionFile)) return false;
|
|
226
|
+
try {
|
|
227
|
+
const storedTag = readFileSync(versionFile, 'utf-8').trim();
|
|
228
|
+
const storedVersion = versionFromTag(storedTag);
|
|
229
|
+
return semverGte(storedVersion, GRAFEMA_VERSION);
|
|
230
|
+
} catch {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Ensure a binary exists and is current, downloading it if missing or stale.
|
|
196
237
|
*
|
|
197
238
|
* This is the main entry point for lazy downloading. Call it before
|
|
198
239
|
* spawning an analyzer binary. Returns the path if found or downloaded,
|
|
199
240
|
* null if the binary can't be obtained.
|
|
200
241
|
*
|
|
242
|
+
* Staleness check: if a binary exists in ~/.grafema/bin/ but its .version
|
|
243
|
+
* file doesn't match the current Grafema release, it is re-downloaded.
|
|
244
|
+
*
|
|
201
245
|
* @param binaryName - e.g. "grafema-analyzer"
|
|
202
246
|
* @param existingPath - path from findBinary() (null = not found locally)
|
|
203
247
|
* @param onProgress - optional callback for download progress
|
|
@@ -207,22 +251,33 @@ export async function ensureBinary(
|
|
|
207
251
|
existingPath: string | null,
|
|
208
252
|
onProgress?: (msg: string) => void,
|
|
209
253
|
): Promise<string | null> {
|
|
210
|
-
// Already found locally
|
|
254
|
+
// Already found locally (e.g. in platform npm package or PATH)
|
|
211
255
|
if (existingPath) return existingPath;
|
|
212
256
|
|
|
213
257
|
// Check ~/.grafema/bin/ first (may have been downloaded previously)
|
|
214
258
|
const cached = findInGrafemaBin(binaryName);
|
|
215
|
-
if (cached) return cached;
|
|
259
|
+
if (cached && isBinaryCurrentVersion(cached)) return cached;
|
|
216
260
|
|
|
217
261
|
// Not downloadable (e.g. rfdb-server — must be in npm package)
|
|
218
|
-
if (!isDownloadable(binaryName))
|
|
262
|
+
if (!isDownloadable(binaryName)) {
|
|
263
|
+
// If cached exists but is stale and not downloadable, return it anyway
|
|
264
|
+
if (cached) return cached;
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Download (missing or stale) — auto-detect latest binaries-v* release tag
|
|
269
|
+
const log = onProgress || (() => {});
|
|
270
|
+
if (cached) {
|
|
271
|
+
log(`Updating ${binaryName} (stale binary detected)...`);
|
|
272
|
+
}
|
|
219
273
|
|
|
220
|
-
// Download
|
|
221
274
|
try {
|
|
222
275
|
return await downloadBinary(binaryName, undefined, onProgress);
|
|
223
276
|
} catch (err) {
|
|
224
277
|
const msg = err instanceof Error ? err.message : String(err);
|
|
225
278
|
(onProgress || console.error)(`Failed to download ${binaryName}: ${msg}`);
|
|
279
|
+
// Fall back to stale binary if download fails
|
|
280
|
+
if (cached) return cached;
|
|
226
281
|
return null;
|
|
227
282
|
}
|
|
228
283
|
}
|