运行时 API
Breeze 插件运行在 QuickJS-NG 引擎中,不是 Node.js 也不是浏览器环境。 下面列出标准 ECMAScript 之外,运行时额外提供的全局 API。
全局对象
插件启动后可直接使用的全局对象:
fetch/Request/Response/HeadersAbortController/AbortSignalURL/URLSearchParamsBlob/File/FormDatastructuredCloneconsolecryptoTextEncoder/TextDecoderBufferfspathnativebridgeuuidv4__web(运行时总线,包含以上全部能力)
推荐入口:hostRuntime
示例仓库提供了类型化的便捷封装,推荐在 TypeScript 插件中使用:
import { hostRuntime } from "../types/runtime-api";
const encoder = new TextEncoder();
const md5 = await hostRuntime.crypto.md5(encoder.encode("hello"));
const sha = hostRuntime.crypto
.createHash("sha256")
.update(encoder.encode("text"))
.digest("hex");
const key = hostRuntime.uuidv4();
const data = await hostRuntime.gzipCompress(new Uint8Array([1, 2, 3]));等价地,你也可以直接操作全局对象:
const encoder = new TextEncoder();
const md5 = await crypto.md5(encoder.encode("hello"));
const sha = crypto
.createHash("sha256")
.update(encoder.encode("text"))
.digest("hex");fetch
标准 fetch 实现。
const res = await fetch("https://api.example.com/data");
const data = await res.json(); // JSON
const text = await res.text(); // 文本
const blob = await res.blob(); // Blob
const buf = await res.arrayBuffer(); // ArrayBuffer配套对象 Request、Response、Headers、AbortController、AbortSignal、FormData、Blob、File 均可用。
// 超时控制
const ac = new AbortController();
setTimeout(() => ac.abort(), 10000);
const res = await fetch(url, { signal: ac.signal });
// 或
const res = await fetch(url, { signal: AbortSignal.timeout(10000) });二进制响应优化
对于返回二进制的接口,在请求头中加入以下字段可让宿主直接以二进制方式解析响应,避免不必要的类型转换:
x-rquickjs-host-offload-binary-v1: 1const res = await fetch(url, {
headers: { "x-rquickjs-host-offload-binary-v1": "1" },
});
const buf = await res.arrayBuffer();bridge
插件与 Rust 宿主通信的唯一桥梁。
方法
bridge.call(name, ...args)— 异步调用宿主路由bridge.callSync(name, ...args)— 同步调用(会阻塞,谨慎使用)bridge.gzipCompress(input)— gzip 压缩bridge.gzipDecompress(input)— gzip 解压
内建路由
以下路由开箱即用,无需注册:
摘要(推荐)
crypto.md5crypto.sha1crypto.sha256crypto.sha512crypto.hmac_sha1crypto.hmac_sha256crypto.hmac_sha512
摘要(旧版,已废弃)
crypto.md5_hexcrypto.sha1_hexcrypto.sha256_hexcrypto.sha512_hexcrypto.hmac_sha1_hexcrypto.hmac_sha256_hexcrypto.hmac_sha512_hex
AES(推荐,输入输出均为原始字节)
crypto.aes_ecb_pkcs7_decryptcrypto.aes_ecb_pkcs7_encryptcrypto.aes_cbc_pkcs7_encryptcrypto.aes_cbc_pkcs7_decryptcrypto.aes_gcm_encryptcrypto.aes_gcm_decrypt
AES(旧版 base64,已废弃)
crypto.aes_ecb_pkcs7_decrypt_b64crypto.aes_cbc_pkcs7_encrypt_b64crypto.aes_cbc_pkcs7_decrypt_b64crypto.aes_gcm_encrypt_b64crypto.aes_gcm_decrypt_b64
压缩
compression.gzip_compresscompression.gzip_decompress
原生
native.putnative.takenative.exec
数学
math.add
说明
- 参数中的二进制数据会自动转为宿主端 buffer
- 返回的二进制数据会自动还原为
Uint8Array
const md5 = await bridge.call("crypto.md5", new TextEncoder().encode("hello"));
const compressed = await bridge.call(
"compression.gzip_compress",
new Uint8Array([1, 2, 3]),
);crypto
Node.js 兼容的加密 API 子集,非完整实现。优先使用 crypto.* 便捷方法,而不是直接调 bridge.call("crypto.*", ...)。
支持的方法
// 流式哈希
crypto.createHash("sha1" | "sha-1")
crypto.createHash("sha256" | "sha-256")
crypto.createHash("sha512" | "sha-512")
// 流式 HMAC
crypto.createHmac("sha1" | "sha-1", key)
crypto.createHmac("sha256" | "sha-256", key)
crypto.createHmac("sha512" | "sha-512", key)
// 便捷摘要(返回 hex 字符串)
crypto.md5(input)
crypto.sha1(input)
crypto.sha256(input)
crypto.sha512(input)
// 便捷 HMAC(返回 hex 字符串)
crypto.hmacSha1(key, input)
crypto.hmacSha256(key, input)
crypto.hmacSha512(key, input)
// 工具
crypto.randomBytes(size) // 返回 Buffer
crypto.randomUUID() // 返回 UUID v4 字符串
crypto.timingSafeEqual(a, b) // 时序安全比较
// PBKDF2(目前固定走 sha256)
crypto.pbkdf2Sync(password, salt, iterations, keyLen, digest?)
crypto.pbkdf2(password, salt, iterations, keyLen, digest?, callback)
// AES 便捷包装(推荐,输入输出为原始字节)
crypto.aesEcbPkcs7Decrypt(input, keyRaw)
crypto.aesEcbPkcs7Encrypt(input, keyRaw)
crypto.aesCbcPkcs7Encrypt(input, keyRaw, ivRaw)
crypto.aesCbcPkcs7Decrypt(input, keyRaw, ivRaw)
crypto.aesGcmEncrypt(input, keyRaw, nonceRaw, aad?)
crypto.aesGcmDecrypt(input, keyRaw, nonceRaw, aad?)
// 旧版 base64 包装(已废弃,仍兼容)
crypto.aesCbcPkcs7EncryptB64(payloadB64, keyRaw, ivRaw)
crypto.aesCbcPkcs7DecryptB64(payloadB64, keyRaw, ivRaw)
crypto.aesGcmEncryptB64(payloadB64, keyRaw, nonceRaw, aadB64?)
crypto.aesGcmDecryptB64(payloadB64, keyRaw, nonceRaw, aadB64?)支持的编码
utf8 / utf-8 / hex / base64 / latin1 / binary / buffer
说明
pbkdf2/pbkdf2Sync目前固定走 sha256- 旧版
_hex/_b64API 因行为较为模糊,已废弃,不再建议使用 - 新版 AES / 摘要 / HMAC API 只接受原始二进制输入(
Uint8Array/ArrayBuffer/ArrayBufferView/number[]),不再接受字符串,也不再内置 base64 编解码- 字符串请先用
new TextEncoder().encode(string)或encodeUtf8(string)转换 - base64 请先用全局
bytesFromBase64(b64)转换为Uint8Array
- 字符串请先用
// 推荐写法
const encoder = new TextEncoder();
const hash = crypto
.createHash("sha256")
.update(encoder.encode("text"))
.digest("hex");
const hmac = crypto
.createHmac("sha256", encoder.encode("key"))
.update(encoder.encode("text"))
.digest("hex");
const md5Hex = await crypto.md5(encoder.encode("text"));fs
文件系统 API,与 Node.js fs/promises 子集兼容。
await fs.promises.writeFile("/tmp/test.txt", "hello");
const raw = await fs.promises.readFile("/tmp/test.txt"); // Uint8Array
const text = await fs.promises.readFile("/tmp/test.txt", "utf8"); // string
await fs.promises.mkdir("/tmp/dir", { recursive: true });
const files = await fs.promises.readdir("/tmp");
await fs.promises.rm("/tmp/test.txt", { force: true });path
路径工具,与 Node.js path 子集兼容。
path.join("/a", "b", "../c"); // "/a/c"
path.resolve("a", "b"); // 绝对路径
path.dirname("/a/b/c.txt"); // "/a/b"
path.basename("/a/b/c.txt"); // "c.txt"
path.extname("/a/b/c.txt"); // ".txt"native
字节缓冲池,用于管理二进制数据。大部分场景用 fetch 和 bridge 即可,不推荐直接操作。
主要方法:
native.put(input)— 将数据放入缓冲池,返回 idnative.take(id)— 从缓冲池取出数据native.free(id)— 释放缓冲native.gzipCompress(input)— gzip 压缩native.gzipDecompress(input)— gzip 解压
console
console.log("...");
console.info("...");
console.warn("...");
console.error("...");
console.debug("...");输出会转到宿主日志。其他 console 方法会 fallback 到 console.log 同级逻辑。
uuidv4
const id = uuidv4();Buffer
Node.js 兼容的 Buffer 子集。
Buffer.from(data, encoding?)
Buffer.alloc(size)
Buffer.isBuffer(obj)
Buffer.byteLength(string, encoding?)TextEncoder / TextDecoder
UTF-8 编解码。
const bytes = new TextEncoder().encode("hello");
const text = new TextDecoder().decode(bytes);structuredClone
const copy = structuredClone({ a: 1, b: [2, 3] });类型定义
示例仓库 types/ 目录包含完整的 TypeScript 类型定义:
types/index.d.ts— 类型统一导出入口types/crypto.d.ts—crypto相关类型types/fs.d.ts—fs/path相关类型types/native.d.ts—native相关类型types/bridge.d.ts—bridge相关类型types/runtime.d.ts— 运行时全局对象与RuntimeApiSettypes/runtime-api.ts—hostRuntime便捷封装types/runtime-api.typecheck.ts— 运行时类型断言示例
建议开发时直接引用这些类型。
便捷封装
示例仓库 src/tools.ts 提供了一些常用功能的便捷封装(cache.*、pluginConfig.*、opencc.*、flutterTools.*、runtime.*),详细用法见源码注释。
常见用法
import { hostRuntime } from "../types/runtime-api";
const encoder = new TextEncoder();
// 1. fetch 拉数据
const res = await fetch("https://api.example.com/list");
const data = await res.json();
// 2. crypto 计算摘要
const md5 = await hostRuntime.crypto.md5(encoder.encode("data"));
const sha256 = hostRuntime.crypto
.createHash("sha256")
.update(encoder.encode("data"))
.digest("hex");
// 3. 写本地文件
await hostRuntime.fs.promises.writeFile("/tmp/result.json", JSON.stringify(data));
// 4. console 打日志
console.log("result:", data);