capiumbrowser 1.0.4 → 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.md +1 -1
- package/lib/channels.json +14 -12
- package/lib/download.js +56 -18
- package/lib/version.js +139 -135
- package/package.json +1 -1
- package/playwright.js +13 -2
- package/puppeteer.js +13 -2
package/README.md
CHANGED
|
@@ -253,7 +253,7 @@ The spoofing lives in the compiled binary — not injected via JavaScript, not s
|
|
|
253
253
|
aligned to a single coherent story.
|
|
254
254
|
|
|
255
255
|
**Download mechanics.** The binary is fetched from the license service with a signed, path-based GET
|
|
256
|
-
(`/download/distro/chromium-v<version>/capiumbrowser-<os>-<arch>.tar.gz`): the key travels in the
|
|
256
|
+
(`/download/distro/chromium-v<version>.<revision>/capiumbrowser-<os>-<arch>.tar.gz`): the key travels in the
|
|
257
257
|
`X-Capzy-License` header (never the URL) and the request path is HMAC-signed. The response's
|
|
258
258
|
`X-Capzy-SHA256` is verified against the streamed bytes before extraction, so a corrupted or tampered
|
|
259
259
|
archive is rejected. Env overrides: `CAPIUM_LICENSE_KEY` (or `~/.capium/license`), `CAPIUM_VERSION` (target
|
package/lib/channels.json
CHANGED
|
@@ -1,29 +1,31 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_comment": "SINGLE SOURCE OF TRUTH for the current stable Capium browser build per OS/arch. Each OS reaches stable independently -- edit one entry without touching the others. This file ships inside the wheel (the SDK reads it to pick each host's stable build) AND is published to the download server by the release pipeline. `version` is the Chromium
|
|
2
|
+
"_comment": "SINGLE SOURCE OF TRUTH for the current stable Capium browser build per OS/arch. Each OS reaches stable independently -- edit one entry without touching the others. This file ships inside the wheel (the SDK reads it to pick each host's stable build) AND is published to the download server by the release pipeline. `version` is the Chromium version (what the browser reports to the customer -- unchanged by the revision); `revision` is our packaging counter -- the served R2 folder is chromium-v<version>.<revision>/, ALWAYS dotted-suffixed starting at 1 (chromium-v<version>.1/ is the first build, .2/ a same-engine re-spin), so publishing a re-spin never overwrites the artifact older SDKs still fetch. `published: false` means the tag is declared but no artifact exists yet -- the SDK raises a clear 'not published yet' error instead of a raw 404.",
|
|
3
3
|
"schema": 1,
|
|
4
|
-
"updated": "2026-09-
|
|
4
|
+
"updated": "2026-09-28",
|
|
5
5
|
"channels": {
|
|
6
6
|
"stable": {
|
|
7
7
|
"windows-x64": {
|
|
8
|
-
"version": "
|
|
9
|
-
"
|
|
10
|
-
"
|
|
8
|
+
"version": "153.0.8010.53",
|
|
9
|
+
"engine_version": "153.0.8010.52",
|
|
10
|
+
"revision": 1,
|
|
11
|
+
"sha256": "6eaea779c665335ffa8585f437527bb5124b72fc730b373bb53d23145fa33026",
|
|
11
12
|
"published": true
|
|
12
13
|
},
|
|
13
14
|
"macos-arm64": {
|
|
14
|
-
"version": "
|
|
15
|
-
"
|
|
16
|
-
"
|
|
15
|
+
"version": "153.0.8010.53",
|
|
16
|
+
"engine_version": "153.0.8010.52",
|
|
17
|
+
"revision": 1,
|
|
18
|
+
"sha256": "a8901553c8c7eabf3b08106bc3784dd270280c82be8484cac800838c41dca40d",
|
|
17
19
|
"published": true
|
|
18
20
|
},
|
|
19
21
|
"linux-x64": {
|
|
20
|
-
"version": "
|
|
21
|
-
"revision":
|
|
22
|
-
"sha256": "
|
|
22
|
+
"version": "153.0.8010.52",
|
|
23
|
+
"revision": 1,
|
|
24
|
+
"sha256": "69f512f01c2bfe202181847e10a76c36f0d1736170fd5bfe861f9ea6bdf5cc02",
|
|
23
25
|
"published": true
|
|
24
26
|
},
|
|
25
27
|
"linux-arm64": {
|
|
26
|
-
"version": "
|
|
28
|
+
"version": "153.0.8010.52",
|
|
27
29
|
"revision": 1,
|
|
28
30
|
"sha256": null,
|
|
29
31
|
"published": false
|
package/lib/download.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* overrides).
|
|
8
8
|
*
|
|
9
9
|
* Download scheme (signed, path-based):
|
|
10
|
-
* GET {server}/download/distro/chromium-v{version}/capiumbrowser-{os}-{arch}.tar.gz
|
|
10
|
+
* GET {server}/download/distro/chromium-v{version}.{revision}/capiumbrowser-{os}-{arch}.tar.gz
|
|
11
11
|
*
|
|
12
12
|
* The license key travels in the X-Capzy-License header (over TLS), NEVER in the URL; the
|
|
13
13
|
* request PATH is HMAC-signed (X-Capzy-Timestamp + X-Capzy-Signature =
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* X-Capzy-SHA256 is verified against the downloaded bytes before anything is extracted.
|
|
16
16
|
*
|
|
17
17
|
* The archive FILENAME is version-independent -- `capiumbrowser-<os>-<arch>.tar.gz` is always
|
|
18
|
-
* the same; only the `chromium-v<version>/` folder changes.
|
|
18
|
+
* the same; only the `chromium-v<version>.<revision>/` folder changes.
|
|
19
19
|
*
|
|
20
20
|
* Source resolution (first that works):
|
|
21
21
|
* CAPIUM_BINARY -> use this exact launch target, no download
|
|
@@ -87,15 +87,15 @@ function downloadTag(system = null, machine = null) {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
/**
|
|
90
|
-
* The signed request path for a build: version in the folder, tag in the filename
|
|
91
|
-
* (`/download/distro/chromium-v<version>/capiumbrowser-<tag>.tar.gz`). Per-OS versions
|
|
92
|
-
* because each tag lives under its own chromium-v<version>/ folder (win/mac .65
|
|
93
|
-
*
|
|
90
|
+
* The signed request path for a build: version.revision in the folder, tag in the filename
|
|
91
|
+
* (`/download/distro/chromium-v<version>.<revision>/capiumbrowser-<tag>.tar.gz`). Per-OS versions
|
|
92
|
+
* work because each tag lives under its own chromium-v<version>.<revision>/ folder (win/mac .65
|
|
93
|
+
* while linux .64). Key travels in the X-Capzy-License header, the path is HMAC-signed, and the bytes
|
|
94
94
|
* are verified against the response's X-Capzy-SHA256.
|
|
95
95
|
*/
|
|
96
96
|
function distroPath(version, tag, revision = 1) {
|
|
97
|
-
//
|
|
98
|
-
//
|
|
97
|
+
// Each packaging revision lands in its own immutable folder chromium-v<version>.<N>/
|
|
98
|
+
// (N>=1), so publishing a re-spin never overwrites the artifact older SDKs fetch.
|
|
99
99
|
return `/download/distro/chromium-v${buildId(version, revision)}/capiumbrowser-${tag}.tar.gz`;
|
|
100
100
|
}
|
|
101
101
|
|
|
@@ -192,6 +192,38 @@ function stampVersion(binPath, version) {
|
|
|
192
192
|
} catch {}
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
/**
|
|
196
|
+
* The buildId (`<version>.<N>`) this host SHOULD run, honoring CAPIUM_* env, or
|
|
197
|
+
* null if it can't be determined (CAPIUM_BINARY override / unsupported platform / bad manifest).
|
|
198
|
+
* Lets the launch path detect+reject a stale binary from an earlier install instead of running it.
|
|
199
|
+
*/
|
|
200
|
+
function expectedBuildId() {
|
|
201
|
+
if (process.env.CAPIUM_BINARY) return null;
|
|
202
|
+
try {
|
|
203
|
+
const tag = downloadTag();
|
|
204
|
+
const envVer = process.env.CAPIUM_VERSION;
|
|
205
|
+
const version = envVer || binaryVersionFor(tag);
|
|
206
|
+
let revision;
|
|
207
|
+
if (process.env.CAPIUM_REVISION) revision = parseInt(process.env.CAPIUM_REVISION, 10);
|
|
208
|
+
else if (envVer) revision = 1;
|
|
209
|
+
else revision = binaryRevisionFor(tag);
|
|
210
|
+
return buildId(version, revision);
|
|
211
|
+
} catch {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** The launch wrapper inside a just-extracted distro dir, or null (scoped, never a global search). */
|
|
217
|
+
function wrapperIn(distroDir) {
|
|
218
|
+
for (const nm of config._wrapperNames()) {
|
|
219
|
+
const p = path.join(distroDir, nm);
|
|
220
|
+
try {
|
|
221
|
+
if (fs.statSync(p).isFile()) return p;
|
|
222
|
+
} catch {}
|
|
223
|
+
}
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
|
|
195
227
|
/**
|
|
196
228
|
* Delete previously-extracted capium distros under `root`. A host only ever holds its own
|
|
197
229
|
* platform's build, so on a version change we drop the stale one before installing the new
|
|
@@ -294,8 +326,8 @@ async function ensureBinary({ version = null, licenseKey = null, server = null }
|
|
|
294
326
|
const envVer = process.env.CAPIUM_VERSION;
|
|
295
327
|
version = version || envVer || binaryVersionFor(tag);
|
|
296
328
|
// A same Chromium version can be re-spun (r2, r3, ...). CAPIUM_REVISION overrides; an explicit
|
|
297
|
-
// CAPIUM_VERSION pin defaults to
|
|
298
|
-
// revision comes from channels.json.
|
|
329
|
+
// CAPIUM_VERSION pin defaults to revision 1 (<version>.1) unless a revision is given;
|
|
330
|
+
// otherwise the per-OS revision comes from channels.json.
|
|
299
331
|
let revision;
|
|
300
332
|
if (process.env.CAPIUM_REVISION) revision = parseInt(process.env.CAPIUM_REVISION, 10);
|
|
301
333
|
else if (envVer) revision = 1;
|
|
@@ -328,12 +360,13 @@ async function ensureBinary({ version = null, licenseKey = null, server = null }
|
|
|
328
360
|
const subdir = `capium-${String(version).split('.')[0]}-${tag}`; // FLAT-archive wrapper name
|
|
329
361
|
const tmp = path.join(os.tmpdir(),
|
|
330
362
|
`capium-dl-${crypto.randomBytes(6).toString('hex')}.tar.gz`);
|
|
363
|
+
let distroDir = null;
|
|
331
364
|
try {
|
|
332
365
|
await download(url, headers, tmp, version, tag);
|
|
333
366
|
// Only drop the stale install once the new bytes are in hand (a failed download must
|
|
334
367
|
// never leave the host with no binary), then extract the new version.
|
|
335
368
|
removeInstalls(root);
|
|
336
|
-
|
|
369
|
+
distroDir = await extract(tmp, root, subdir);
|
|
337
370
|
// Stamp the version marker BEFORE discovery: the FLAT Windows tar carries no capium
|
|
338
371
|
// marker files, and findBinary only accepts a bare chrome.exe next to one -- the
|
|
339
372
|
// downloader vouches for the directory it just extracted.
|
|
@@ -346,13 +379,17 @@ async function ensureBinary({ version = null, licenseKey = null, server = null }
|
|
|
346
379
|
} catch {}
|
|
347
380
|
}
|
|
348
381
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
382
|
+
// Return the binary we JUST extracted (scoped to distroDir), never a global findBinary here --
|
|
383
|
+
// a stale binary in another base could otherwise be returned instead of the fresh build.
|
|
384
|
+
let binPath = wrapperIn(distroDir);
|
|
385
|
+
if (!binPath) {
|
|
386
|
+
try {
|
|
387
|
+
binPath = config.findBinary();
|
|
388
|
+
} catch {
|
|
389
|
+
throw new CapiumError(
|
|
390
|
+
`downloaded and extracted the ${tag} build but no launch target was found afterwards ` +
|
|
391
|
+
`(unexpected archive layout under ${root}).`);
|
|
392
|
+
}
|
|
356
393
|
}
|
|
357
394
|
stampVersion(binPath, bid); // so a later version/revision bump knows to re-download
|
|
358
395
|
// Re-apply exec bits the wrapper + engine binaries need (zip drops unix perms).
|
|
@@ -372,6 +409,7 @@ module.exports = {
|
|
|
372
409
|
destRoot,
|
|
373
410
|
ensureBinary,
|
|
374
411
|
installedVersion,
|
|
412
|
+
expectedBuildId,
|
|
375
413
|
_SUPPORTED: SUPPORTED,
|
|
376
414
|
_normOs: normOs,
|
|
377
415
|
_normArch: normArch,
|
package/lib/version.js
CHANGED
|
@@ -1,135 +1,139 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Version of the capium Node SDK (independent of the browser binary version).
|
|
3
|
-
*
|
|
4
|
-
* The SDK version and the Capium/Chromium binary version move on separate cadences: you update
|
|
5
|
-
* the SDK with `npm install -U capiumbrowser`, and the SDK fetches the *default* binary build to
|
|
6
|
-
* match. Crucially that default is **per platform** -- each OS/arch reaches a stable Capium build
|
|
7
|
-
* independently (Windows can sit on 150 while macOS is on 151).
|
|
8
|
-
*
|
|
9
|
-
* The stable build for each OS is not hardcoded here; it comes from `channels.json`, which ships
|
|
10
|
-
* inside the package and is the single source of truth (the release pipeline edits that file to
|
|
11
|
-
* promote an OS to a new stable, and the same file is published to the download server). This
|
|
12
|
-
* module just loads it; FALLBACK_VERSIONS is used only if the bundled manifest is missing or
|
|
13
|
-
* corrupt in an install.
|
|
14
|
-
*
|
|
15
|
-
* Override order at download time: CAPIUM_VERSION env > per-OS stable from channels.json.
|
|
16
|
-
*/
|
|
17
|
-
'use strict';
|
|
18
|
-
|
|
19
|
-
const fs = require('fs');
|
|
20
|
-
const os = require('os');
|
|
21
|
-
const path = require('path');
|
|
22
|
-
|
|
23
|
-
const SDK_VERSION = require('../package.json').version;
|
|
24
|
-
|
|
25
|
-
// Used only if channels.json can't be read (corrupt/removed install). ensureBinary() raises a
|
|
26
|
-
// clear error long before the "unsupported platform" case matters; this keeps lookups total.
|
|
27
|
-
const FALLBACK_VERSIONS = {
|
|
28
|
-
'windows-x64': '
|
|
29
|
-
'macos-arm64': '
|
|
30
|
-
'linux-x64': '
|
|
31
|
-
'linux-arm64': '
|
|
32
|
-
};
|
|
33
|
-
const DEFAULT_BINARY_VERSION = '
|
|
34
|
-
|
|
35
|
-
function loadStable() {
|
|
36
|
-
// The `channels.stable` map from the bundled manifest, or null if unreadable.
|
|
37
|
-
try {
|
|
38
|
-
const raw = fs.readFileSync(path.join(__dirname, 'channels.json'), 'utf8');
|
|
39
|
-
const stable = JSON.parse(raw).channels.stable;
|
|
40
|
-
return stable && typeof stable === 'object' ? stable : null;
|
|
41
|
-
} catch {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const STABLE = loadStable();
|
|
47
|
-
|
|
48
|
-
function versionsFromManifest() {
|
|
49
|
-
if (!STABLE) return { ...FALLBACK_VERSIONS };
|
|
50
|
-
const out = {};
|
|
51
|
-
for (const [tag, entry] of Object.entries(STABLE)) {
|
|
52
|
-
if (entry && typeof entry === 'object' && entry.version) out[tag] = entry.version;
|
|
53
|
-
}
|
|
54
|
-
return Object.keys(out).length ? out : { ...FALLBACK_VERSIONS };
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Default stable Capium binary build per distro tag, resolved from channels.json.
|
|
58
|
-
const CAPIUM_BINARY_VERSIONS = versionsFromManifest();
|
|
59
|
-
|
|
60
|
-
/** The current stable Capium binary version for a distro tag (e.g. 'windows-x64'). */
|
|
61
|
-
function binaryVersionFor(tag) {
|
|
62
|
-
return CAPIUM_BINARY_VERSIONS[tag] || DEFAULT_BINARY_VERSION;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function revisionsFromManifest() {
|
|
66
|
-
if (!STABLE) return {};
|
|
67
|
-
const out = {};
|
|
68
|
-
for (const [tag, entry] of Object.entries(STABLE)) {
|
|
69
|
-
if (entry && typeof entry === 'object' && Number.isInteger(entry.revision)) out[tag] = entry.revision;
|
|
70
|
-
}
|
|
71
|
-
return out;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Re-spin variant per tag (>=1). Same Chromium version can be rebuilt (a stealth/fingerprint
|
|
75
|
-
// change with no engine bump); each re-spin increments this. 1 = the base build.
|
|
76
|
-
const CAPIUM_BINARY_REVISIONS = revisionsFromManifest();
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* The
|
|
80
|
-
* are re-spins of the SAME Chromium version served from chromium-v<version
|
|
81
|
-
* never overwrites the
|
|
82
|
-
*/
|
|
83
|
-
function binaryRevisionFor(tag) {
|
|
84
|
-
return CAPIUM_BINARY_REVISIONS[tag] || 1;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Stable identity of one specific build = the R2 folder discriminator AND the install-cache key.
|
|
89
|
-
*
|
|
90
|
-
* (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Version of the capium Node SDK (independent of the browser binary version).
|
|
3
|
+
*
|
|
4
|
+
* The SDK version and the Capium/Chromium binary version move on separate cadences: you update
|
|
5
|
+
* the SDK with `npm install -U capiumbrowser`, and the SDK fetches the *default* binary build to
|
|
6
|
+
* match. Crucially that default is **per platform** -- each OS/arch reaches a stable Capium build
|
|
7
|
+
* independently (Windows can sit on 150 while macOS is on 151).
|
|
8
|
+
*
|
|
9
|
+
* The stable build for each OS is not hardcoded here; it comes from `channels.json`, which ships
|
|
10
|
+
* inside the package and is the single source of truth (the release pipeline edits that file to
|
|
11
|
+
* promote an OS to a new stable, and the same file is published to the download server). This
|
|
12
|
+
* module just loads it; FALLBACK_VERSIONS is used only if the bundled manifest is missing or
|
|
13
|
+
* corrupt in an install.
|
|
14
|
+
*
|
|
15
|
+
* Override order at download time: CAPIUM_VERSION env > per-OS stable from channels.json.
|
|
16
|
+
*/
|
|
17
|
+
'use strict';
|
|
18
|
+
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const os = require('os');
|
|
21
|
+
const path = require('path');
|
|
22
|
+
|
|
23
|
+
const SDK_VERSION = require('../package.json').version;
|
|
24
|
+
|
|
25
|
+
// Used only if channels.json can't be read (corrupt/removed install). ensureBinary() raises a
|
|
26
|
+
// clear error long before the "unsupported platform" case matters; this keeps lookups total.
|
|
27
|
+
const FALLBACK_VERSIONS = {
|
|
28
|
+
'windows-x64': '153.0.8010.52', // real Chrome 152 stable per OS (win/mac .65, linux .64)
|
|
29
|
+
'macos-arm64': '153.0.8010.52',
|
|
30
|
+
'linux-x64': '153.0.8010.52',
|
|
31
|
+
'linux-arm64': '153.0.8010.52', // declared; not yet published (see channels.json)
|
|
32
|
+
};
|
|
33
|
+
const DEFAULT_BINARY_VERSION = '153.0.8010.52';
|
|
34
|
+
|
|
35
|
+
function loadStable() {
|
|
36
|
+
// The `channels.stable` map from the bundled manifest, or null if unreadable.
|
|
37
|
+
try {
|
|
38
|
+
const raw = fs.readFileSync(path.join(__dirname, 'channels.json'), 'utf8');
|
|
39
|
+
const stable = JSON.parse(raw).channels.stable;
|
|
40
|
+
return stable && typeof stable === 'object' ? stable : null;
|
|
41
|
+
} catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const STABLE = loadStable();
|
|
47
|
+
|
|
48
|
+
function versionsFromManifest() {
|
|
49
|
+
if (!STABLE) return { ...FALLBACK_VERSIONS };
|
|
50
|
+
const out = {};
|
|
51
|
+
for (const [tag, entry] of Object.entries(STABLE)) {
|
|
52
|
+
if (entry && typeof entry === 'object' && entry.version) out[tag] = entry.version;
|
|
53
|
+
}
|
|
54
|
+
return Object.keys(out).length ? out : { ...FALLBACK_VERSIONS };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Default stable Capium binary build per distro tag, resolved from channels.json.
|
|
58
|
+
const CAPIUM_BINARY_VERSIONS = versionsFromManifest();
|
|
59
|
+
|
|
60
|
+
/** The current stable Capium binary version for a distro tag (e.g. 'windows-x64'). */
|
|
61
|
+
function binaryVersionFor(tag) {
|
|
62
|
+
return CAPIUM_BINARY_VERSIONS[tag] || DEFAULT_BINARY_VERSION;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function revisionsFromManifest() {
|
|
66
|
+
if (!STABLE) return {};
|
|
67
|
+
const out = {};
|
|
68
|
+
for (const [tag, entry] of Object.entries(STABLE)) {
|
|
69
|
+
if (entry && typeof entry === 'object' && Number.isInteger(entry.revision)) out[tag] = entry.revision;
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Re-spin variant per tag (>=1). Same Chromium version can be rebuilt (a stealth/fingerprint
|
|
75
|
+
// change with no engine bump); each re-spin increments this. 1 = the base build.
|
|
76
|
+
const CAPIUM_BINARY_REVISIONS = revisionsFromManifest();
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The packaging revision (>=1) for a distro tag. 1 = the first build (chromium-v<version>.1/);
|
|
80
|
+
* 2,3,... are re-spins of the SAME Chromium version served from chromium-v<version>.<N>/ (so a
|
|
81
|
+
* re-spin never overwrites the artifact older SDKs still fetch). A version bump resets this to 1.
|
|
82
|
+
*/
|
|
83
|
+
function binaryRevisionFor(tag) {
|
|
84
|
+
return CAPIUM_BINARY_REVISIONS[tag] || 1;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Stable identity of one specific build = the R2 folder discriminator AND the install-cache key.
|
|
89
|
+
* The packaging revision is ALWAYS a dotted suffix starting at 1: chromium-v<version>.<N>/
|
|
90
|
+
* (revision 1 -> <version>.1, the first build; 2,3,... -> <version>.2 etc., a same-engine
|
|
91
|
+
* re-spin). Each revision is its own immutable folder, so a re-spin never overwrites the
|
|
92
|
+
* artifact an older SDK still fetches, and a revision bump re-downloads. NOTE: the customer's
|
|
93
|
+
* reported Chrome version is unchanged -- this suffix only names our distro/upload/download
|
|
94
|
+
* artifact, not the browser version.
|
|
95
|
+
*/
|
|
96
|
+
function buildId(version, revision) {
|
|
97
|
+
const n = parseInt(revision, 10);
|
|
98
|
+
return `${version}.${!n || n < 1 ? 1 : n}`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* False only when the manifest declares the tag but marks it not-yet-published. Unknown
|
|
103
|
+
* tags / missing manifest return true so the download layer's own error/404 speaks instead.
|
|
104
|
+
*/
|
|
105
|
+
function isPublished(tag) {
|
|
106
|
+
if (!STABLE) return true;
|
|
107
|
+
const entry = STABLE[tag];
|
|
108
|
+
if (!entry || typeof entry !== 'object') return true;
|
|
109
|
+
return entry.published !== false;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Best-effort distro tag for the current host, mirroring download.js's mapping. Kept
|
|
114
|
+
* dependency-free (no require of download.js) so version.js stays loadable in isolation.
|
|
115
|
+
*/
|
|
116
|
+
function hostTag() {
|
|
117
|
+
const p = process.platform;
|
|
118
|
+
const osName = p === 'darwin' ? 'macos' : p === 'win32' ? 'windows' : 'linux';
|
|
119
|
+
const m = os.arch();
|
|
120
|
+
const arch = m === 'x64' || m === 'ia32' ? 'x64' : m === 'arm64' ? 'arm64' : m;
|
|
121
|
+
return `${osName}-${arch}`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// The stable build this SDK targets for THIS host (CLI display, examples). Code that fetches a
|
|
125
|
+
// build should prefer binaryVersionFor(tag) with the tag it already resolved.
|
|
126
|
+
const CAPIUM_BINARY_VERSION = binaryVersionFor(hostTag());
|
|
127
|
+
|
|
128
|
+
module.exports = {
|
|
129
|
+
SDK_VERSION,
|
|
130
|
+
CAPIUM_BINARY_VERSION,
|
|
131
|
+
CAPIUM_BINARY_VERSIONS,
|
|
132
|
+
CAPIUM_BINARY_REVISIONS,
|
|
133
|
+
binaryVersionFor,
|
|
134
|
+
binaryRevisionFor,
|
|
135
|
+
buildId,
|
|
136
|
+
isPublished,
|
|
137
|
+
hostTag,
|
|
138
|
+
_FALLBACK_VERSIONS: FALLBACK_VERSIONS,
|
|
139
|
+
};
|
package/package.json
CHANGED
package/playwright.js
CHANGED
|
@@ -42,12 +42,23 @@ function requireDriver() {
|
|
|
42
42
|
|
|
43
43
|
/** Find the capium wrapper; if absent, try to download it (see lib/download). */
|
|
44
44
|
async function resolveBinary(binary, licenseKey) {
|
|
45
|
+
// Explicit override (arg or CAPIUM_BINARY) wins with no version check -- the caller's choice.
|
|
46
|
+
if (binary || process.env.CAPIUM_BINARY) return config.findBinary(binary);
|
|
47
|
+
// Otherwise the discovered binary must be the CURRENT target build. A stale binary left by an
|
|
48
|
+
// earlier install (older revision -> older device pool / pre-fix fingerprint) must never be
|
|
49
|
+
// launched silently even after `npm i -U` -- it still trips detection. Re-fetch on a mismatch.
|
|
50
|
+
const want = download.expectedBuildId();
|
|
45
51
|
try {
|
|
46
|
-
|
|
52
|
+
const found = config.findBinary();
|
|
53
|
+
const have = download.installedVersion(found);
|
|
54
|
+
if (want === null || have === want) return found;
|
|
55
|
+
process.stderr.write(
|
|
56
|
+
`capium: ignoring stale binary at ${found} (build ${have}; current target ${want}) and ` +
|
|
57
|
+
`fetching the current build. Delete it or set CAPIUM_BINARY to silence this.\n`);
|
|
47
58
|
} catch (e) {
|
|
48
59
|
if (e.code !== 'ENOENT') throw e;
|
|
49
|
-
return download.ensureBinary({ licenseKey });
|
|
50
60
|
}
|
|
61
|
+
return download.ensureBinary({ licenseKey });
|
|
51
62
|
}
|
|
52
63
|
|
|
53
64
|
/**
|
package/puppeteer.js
CHANGED
|
@@ -45,12 +45,23 @@ function requireDriver() {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
async function resolveBinary(binary, licenseKey) {
|
|
48
|
+
// Explicit override (arg or CAPIUM_BINARY) wins with no version check -- the caller's choice.
|
|
49
|
+
if (binary || process.env.CAPIUM_BINARY) return config.findBinary(binary);
|
|
50
|
+
// Otherwise the discovered binary must be the CURRENT target build. A stale binary left by an
|
|
51
|
+
// earlier install (older revision -> older device pool / pre-fix fingerprint) must never be
|
|
52
|
+
// launched silently even after `npm i -U` -- it still trips detection. Re-fetch on a mismatch.
|
|
53
|
+
const want = download.expectedBuildId();
|
|
48
54
|
try {
|
|
49
|
-
|
|
55
|
+
const found = config.findBinary();
|
|
56
|
+
const have = download.installedVersion(found);
|
|
57
|
+
if (want === null || have === want) return found;
|
|
58
|
+
process.stderr.write(
|
|
59
|
+
`capium: ignoring stale binary at ${found} (build ${have}; current target ${want}) and ` +
|
|
60
|
+
`fetching the current build. Delete it or set CAPIUM_BINARY to silence this.\n`);
|
|
50
61
|
} catch (e) {
|
|
51
62
|
if (e.code !== 'ENOENT') throw e;
|
|
52
|
-
return download.ensureBinary({ licenseKey });
|
|
53
63
|
}
|
|
64
|
+
return download.ensureBinary({ licenseKey });
|
|
54
65
|
}
|
|
55
66
|
|
|
56
67
|
async function prepare(opts) {
|