Files
raycast-api/tests/fixtures/mock_bundle.mjs
T

78 lines
3.0 KiB
JavaScript

// Synthetic bundle for raycast_api.discovery tests.
//
// Structurally mirrors Raycast's bundle: a rot13+rot5 function, an async
// 4-param HMAC signer that .map()s through the rot fn, and a couple of decoys
// the extractor must reject. Identifier names are intentionally NOT the
// minified ones from real Raycast (Sur, Nkt) — we use longer names to prove
// the extractor matches structurally, not by name.
// --- decoy 1: 1-param but missing the rot triplets ----------------------
function decoyOneParam(t) {
return t.toUpperCase();
}
// --- decoy 2: 4-param HMAC-ish but with no .map(rot) call --------------
async function decoyHmac(a, b, c, d) {
// Mentions HMAC + SHA-256 + importKey but never calls .map(rotFn).
let key = await crypto.subtle.importKey("raw", a, {
name: "HMAC",
hash: "SHA-256"
}, false, ["sign"]);
return crypto.subtle.sign("HMAC", key, b);
}
// --- the real rot fn ----------------------------------------------------
function RotXform(s) {
let out = "";
for (let ch of s) {
let r = ch.charCodeAt(0);
if (r >= 65 && r <= 90) {
out += String.fromCharCode((r - 65 + 13) % 26 + 65);
} else if (r >= 97 && r <= 122) {
out += String.fromCharCode((r - 97 + 13) % 26 + 97);
} else if (r >= 48 && r <= 57) {
out += String.fromCharCode((r - 48 + 5) % 10 + 48);
} else {
out += ch;
}
}
return out;
}
// --- duplicate rot (real bundle has two byte-identical copies) ---------
function RotXform2(s) {
let out = "";
for (let ch of s) {
let r = ch.charCodeAt(0);
if (r >= 65 && r <= 90) { out += String.fromCharCode((r - 65 + 13) % 26 + 65); }
else if (r >= 97 && r <= 122) { out += String.fromCharCode((r - 97 + 13) % 26 + 97); }
else if (r >= 48 && r <= 57) { out += String.fromCharCode((r - 48 + 5) % 10 + 48); }
else { out += ch; }
}
return out;
}
// --- the real signing fn -----------------------------------------------
async function SignReq(secret, timestamp, deviceId, body) {
let enc = new TextEncoder().encode(body);
let h = await crypto.subtle.digest("SHA-256", enc);
let bodyHash = Array.from(new Uint8Array(h)).map(b => b.toString(16).padStart(2, "0")).join("");
let canonical = [timestamp, deviceId, bodyHash].map(RotXform).join(".");
let keyBytes = new TextEncoder().encode(secret);
let canonBytes = new TextEncoder().encode(canonical);
let key = await crypto.subtle.importKey("raw", keyBytes, {
name: "HMAC",
hash: "SHA-256"
}, false, ["sign"]);
let sig = await crypto.subtle.sign("HMAC", key, canonBytes);
return Array.from(new Uint8Array(sig)).map(b => b.toString(16).padStart(2, "0")).join("");
}
// Decoy: looks like a string-handling function but with a `/` inside a
// regex literal — exercises the regex-aware brace matcher.
function noiseFn(input) {
return input.replace(/\}/g, "_");
}
export { SignReq, RotXform };