# @ezkljs/engine 中文文档

规范地址：https://npmcn.com/package/%40ezkljs/engine/

版本：22\.0\.1
npm 元数据更新时间：2025-04-23T08:53:19.797Z
中文译文更新时间：2026-11-14T07:01:52.705Z
软件包许可：未声明

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40ezkljs/engine
原文对照：https://npmcn.com/package/%40ezkljs/engine/?lang=original

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：19.7 MB，14 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：2 个
- 首次发布：2023-08-11T00:13:41.052Z
- 最新版本发布：2025-04-23T08:53:19.548Z
- 近 30 天下载量：2592（2026-10-14 至 2026-11-12，npm 官方下载统计）
- 已发布版本数：116（近 12 个月 0 个）

## 中文简介

要安装 EZKL 引擎, 只需使用您最喜欢的软件包管理器 :

## 安装

```sh
npm install @ezkljs/engine
```

也可以使用：`pnpm add @ezkljs/engine`、`yarn add @ezkljs/engine`、`bun add @ezkljs/engine`

## README

## 安装

要安装 EZKL 引擎, 只需使用您最喜欢的软件包管理器 :

```shell
# npm
npm install @ezkljs/engine

# yarn
yarn add @ezkljs/engine

# pnpm
pnpm add @ezkljs/engine
```

* * *

在浏览器/nodejs上下文中

-   [遗传](https://npmcn.com/package/%40ezkljs/engine/#readme-genWitness): 从给定输入生成一个证人.
-   [椭圆形](https://npmcn.com/package/%40ezkljs/engine/#readme-elgamal-variables): 从随机种子中生成一个 El-Gamal 键帕.
-   [椭圆](https://npmcn.com/package/%40ezkljs/engine/#readme-elgamal-encrypt): 使用 ElGamal 公钥和随机性加密任意消息.
-   [椭圆](https://npmcn.com/package/%40ezkljs/engine/#readme-elgamal-decrypt): 使用 ElGamal 密钥解密密码文本
-   [证明](https://npmcn.com/package/%40ezkljs/engine/#readme-prove): 生成一个证明
-   [校验](https://npmcn.com/package/%40ezkljs/engine/#readme-verify): 验证给定的证据
-   [马来多哈什](https://npmcn.com/package/%40ezkljs/engine/#readme-hash): 使用 Poseidon 散列函数的给定消息 hash

以及一些帮助器功能,这些功能使得与引擎的工作更加容易:

-   [vecU64 向 Felt 移动](https://npmcn.com/package/%40ezkljs/engine/#readme-vecU64ToFelt): 将 4u64s 转换为字段元素( hex string)
-   [vecU64 输入](https://npmcn.com/package/%40ezkljs/engine/#readme-vecU64ToInt): 将直接代表字段元素的 4u64s 转换为整数
-   [vecU64 移动](https://npmcn.com/package/%40ezkljs/engine/#readme-vecU64ToFloat): 将直接代表一个字段元素的 4 u64s 转换为( 从固定点缩放调整) 浮动点
-   [浮点图VecU64](https://npmcn.com/package/%40ezkljs/engine/#readme-floatToVecU64): 将浮动点元素转换为代表固定点字段元素的 4u64s
-   [缓冲器ToVecOfVecU64](https://npmcn.com/package/%40ezkljs/engine/#readme-bufferToVecOfVecU64): 将4u64s的向量转换为缓冲

为了了解更多如何使用这些帮助方法, 看看我们为他们写的测试 [这里](https://github.com/zkonduit/ezkljs-engine/tree/main/tests/fieldElementUtils.test.ts)

引擎方法在后端使用web组装支持在浏览器/JS上下文中运行生锈码. 从 WASM 绑定中传递和返回的非原始数据类型必须采用序列(缓冲)格式. 这些序列化和去序列化方法使得JS对象更容易被转换成一种可以被引擎方法接受的格式.

-   [序列化](https://npmcn.com/package/%40ezkljs/engine/#readme-serialize): 将给定文物的JS对象表示转换为可以被引擎方法接受的格式.
-   [淡化](https://npmcn.com/package/%40ezkljs/engine/#readme-deserialize): 将特定文物的序列化代表物转换为JS对象.

* * *

### 节点对 Web 目标

引擎有两个目标: `nodejs` 财务报告和审定财务报表 `web`编辑 `nodejs` 目标用于节点应用程序(即节点服务器侧数据处理)和 `web` 目标用于浏览器应用程序(即反应前端)。 从守规矩的角度看,唯一的 两者的区别在于:网络捆绑通过网络工人实例支持多条读取,而节点则不支持.

这个readme将专注于记录网页目标. 如果您有兴趣使用节点目标,请参见单位测试 我们为 [他们](https://github.com/zkonduit/ezkljs-engine/tree/main/tests)。 。 。 .

如果您只想跳入查看一个显示如何使用所有核心引擎绑定的示例应用程序 [此应用程序](https://ezkljs-engine.vercel.app/)的代码 [这里](https://github.com/zkonduit/ezkljs-engine/tree/main/app)

### 十字起源隔离.

要在所有浏览器中使用“ 共享箭头缓冲器” 特性, 您需要确保全局性 `crossOriginIsolated` 设置为 `true`否则, ezkljs 引擎绑定可能行不通, 因为WebAssembly内存由主线程和网络工人共享 。 跟随 [本指南](https://github.com/GoogleChrome/web.dev/blob/main/src/site/content/en/secure/cross-origin-isolation-guide/index.md) 通过google来确保您的网络应用程序是交叉源代码隔离的. 在使用下个js构建的应用示例中,我们通过在下个应用中添加以下内容,实现了跨源隔离. 相会. js 文件 :

```javascript
const nextConfig = {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          {
            key: 'Cross-Origin-Embedder-Policy',
            value: 'require-corp',
          },
          {
            key: 'Cross-Origin-Opener-Policy',
            value: 'same-origin',
          },
        ],
      },
    ]
  },
}
```

### 引擎调试

为了让引擎重回错误 我们建议调用 `init_panic_hook` 在调用其他任何引擎方法之前使用. 这将确保引擎出错以可读格式登录到控制台上,否则,如果出现出错,会以可读格式登录到控制台上 `RuntimeError: unreachable`

如果您还想要从引擎中打印调试数据, 您可以调用 `init_logger` 方法。 这将打印出所有调试数据到控制台 .

### 证明一个新的网络集合实例.

如果您正在使用 Web 捆绑, 您首先需要初始化一个 Web 组装模块, 然后再使用引擎曝光的任何方法 。 要导入默认导出 `@ezkljs/engine/web/ezkl.js` 然后唤作. 如果您想要超越默认的 WASM 内存大小, 您可以通过 Web Assembly 。 记忆对象作为第二个参数. 我们强烈建议这样做,如果您想要您的应用程序与移动浏览器兼容的话,因为默认内存分配对于iOS浏览器来说太大了. 从我们的实验中,我们发现iOS浏览器所能处理的最大内存分配是4096 mb(默认为65536 mb).

```typescript
import init, { init_panic_hook, init_logger } from '@ezkljs/engine/web/ezkl.js'

export default function Home() {
  useEffect(() => {
    async function run() {
      // Initialize the WASM module. Here we are overiding the default memory allocation with the recommend allocation for the best performance across all mobile browsers.
      await init(
        undefined,
        new WebAssembly.Memory({ initial: 20, maximum: 4096, shared: true }),
      )
      // Initialize the panic hook and logger
      init_panic_hook()
      init_logger()
    }
    run()
  })
}
```

### 生成证人

要从给定输入中生成一个证人,您可以使用 `genWitness` 方法。 你可以把目击证人看作是输入输出对,通过对输入进行量化,通过被量化的模型运行,并进行任意散开或加密生成的输入对. 这个目击文件包含了证明诸如"我在这个数据上运行了我的神经网络,它产生了这个输出"等陈述所需的输入和输出对. 链接到示例应用程序中在此使用的方法 : [手柄GenWitness 按钮](https://github.com/zkonduit/ezkljs-engine/blob/main/app/Utils.tsx#L229)

```typescript
import { genWitness, deserialize } from '@ezkljs/engine/web'

// This is the code for the button that triggers the
// witness generation that we used in the example app.

export async function handleGenWitnessButton<T extends FileMapping>(
  files: T,
): Promise<Uint8ArrayResult> {
  const result = await convertFilesToFilesSer(files)
  const start = performance.now() // Start the timer

  let output = genWitness(result['compiled_model'], result['input'])

  let witness = deserialize(output)

  console.log(JSON.stringify(witness, null, 2))

  const end = performance.now() // End the timer

  return {
    output: output,
    executionTime: end - start,
  }
}
```

输出 :

```json
{
  "inputs": [
    [
      [
        "14385415396251402209",
        "2429374486035521128",
        "12558163205804149944",
        "2583518171365219058"
      ],
      [
        "6425625360762666998",
        "7924344314350639699",
        "14762033076929465436",
        "2023505479389396574"
      ],
      [
        "1949230679015292902",
        "16913946402569752895",
        "5177146667339417225",
        "1571765431670520771"
      ]
    ]
  ],
  "outputs": [
    [
      [
        "415066004289224689",
        "11886516471525959549",
        "3696305541684646538",
        "3035258219084094862"
      ],
      [
        "956231351009279921",
        "10951436676983309100",
        "2250248050743556928",
        "1228298028208591648"
      ],
      [0, 0, 0, 0],
      [0, 0, 0, 0]
    ]
  ],
  "processed_inputs": null,
  "processed_params": null,
  "processed_outputs": null,
  "max_lookup_inputs": 22
}
```

### 平均变量

您可以从随机种子中生成一个随机的 ElGamal 键盘, 用于加密和解密 `elgamalGenRandom` 方法.

```typescript
import { elgamalGenRandom, deserialize } from '@ezkljs/engine/web'

// Function to generate a 256 bit seed in the browser
// using a cryptographically secure source of randomness.
// DO NOT USE MATH.RANDOM AS ITS NOT A SECURE SOURCE OF RANDOMNESS
function generate256BitSeed(): Uint8ClampedArray {
  const uuid = self.crypto.randomUUID()
  const buffer = new TextEncoder().encode(uuid)
  let seed = self.crypto.getRandomValues(buffer)
  seed = seed.slice(0, 32)
  return new Uint8ClampedArray(seed.buffer)
}

// Function to convert the return buffer elgamalGenRandom into a JSON object
function uint8ArrayToJsonObject(uint8Array) {
  let string = new TextDecoder().decode(uint8Array)
  let jsonObject = JSONBig.parse(string)
  return jsonObject
}

const buffer = elgamalGenRandom(generate256BitSeed())

// We can take a look at the serialized contents of the
// buffer returned by elgamalGenRandom by converting
// the Uint8Array to a JSON object
let elgamalVariables = deserialize(buffer)

console.log(JSON.stringify(elgamalVariables, null, 2))
```

输出 :

```json
{
  "r": [
    "3454421873345507054",
    "16808310348879090885",
    "8288793628600014913",
    "1828575853528138165"
  ],
  "sk": [
    "8833745371820985590",
    "8074024378078747364",
    "11905923764904461178",
    "851912620759564510"
  ],
  "pk": [
    [
      "10721601427614006364",
      "165460855961439422",
      "2494139285445986520",
      "993922445972607230"
    ],
    [
      "11418900806032782576",
      "15880182954156597531",
      "16112055391177898581",
      "485390167428225782"
    ]
  ],
  "aux_generator": [
    [
      "13503889609873471352",
      "8660427972151475473",
      "16373159693836788928",
      "3475191407935738629"
    ],
    [
      "9899281824843853575",
      "11168630486339379471",
      "550474616581266472",
      "3277527638473654200"
    ]
  ],
  "window_size": 4
}
```

* * *

### 同步加密

使用上一个步骤的公钥(pk)和随机性(r),您可以使用 `elgamalEncrypt` 方法. 在例应用中,我们用这个 [埃尔加马尔- 齐普FileDownload 中](https://github.com/zkonduit/ezkljs-engine/blob/main/app/Utils.tsx#L84) 下载方法 r, sk和pk 字段的 elgamalVariables 作为 JSON 文件.

一旦您通过点击页面上方的"Generate"按钮下载了您的Elgamal变量, 您可以在下载文件夹中解开“ elgamal var” 文件 .

在此之后,您需要创建包含您想要加密的信件的文本文件 .  
由于精液加密是ZKP操作,我们需要将信件转换为 以 u254 表示的序列字段元素。 我们把现场元素序列化 通过将每个u254字段元素分解为4个u64.

用于参考, 请检查示例信件文件 [这里](https://github.com/zkonduit/ezkljs-engine/tree/main/public/data/message.txt)

```typescript
import { elgamalEncrypt, deserialize } from '@ezkljs/engine/web'

// This is the code for the button that triggers the
// generation of the elgamal encyrption ciphertext.

export async function handleGenElgamalEncryptionButton<T extends FileMapping>(
  files: T,
): Promise<Uint8ArrayResult> {
  const result = await convertFilesToFilesSer(files)

  const start = performance.now() // Start the timer

  let output = elgamalEncrypt(result['pk'], result['message'], result['r'])

  const end = performance.now() // End the timer

  let cipherText = deserialize(output)

  console.log(JSON.stringify(cipherText, null, 2))

  return {
    output: output,
    executionTime: end - start,
  }
}
```

输出 :

```json
[
  [
    [
      "10209188590651781239",
      "1606867371818388001",
      "2009969314029440862",
      "68539226482053667"
    ],
    [
      "11542493346099842483",
      "15506753538305362096",
      "11085744708984070406",
      "1449434265777497591"
    ],
    [
      "14888253900846995994",
      "17596893823803099477",
      "7958618303962015576",
      "30430041561409514"
    ]
  ],
  [
    [
      "10873062863189913544",
      "1639997932972316199",
      "7128784801669346971",
      "2001604198948701760"
    ],
    [
      "10873062863189913545",
      "1639997932972316199",
      "7128784801669346971",
      "2001604198948701760"
    ]
  ]
]
```

* * *

### 椭圆解密

使用前一步的密钥(sk)和密码文本,可以使用 `elgamalDecrypt` 方法. 示例应用中使用的方法 : [手柄 GenElgal 解析按钮](https://github.com/zkonduit/ezkljs-engine/blob/main/app/Utils.tsx#L212)

```typescript
import { elgamalDecrypt, deserialize } from '@ezkljs/engine/web'

// This is the code for the button that triggers the
// generation of the elgamal decryption of the ciphertext.
export async function handleGenElgamalDecryptionButton<T extends FileMapping>(
  files: T,
): Promise<Uint8ArrayResult> {
  const result = await convertFilesToFilesSer(files)
  const start = performance.now() // Start the timer

  let output = elgamalDecrypt(result['cipher'], result['sk'])

  const end = performance.now() // End the timer

  let message = deserialize(output)

  console.log(JSON.stringify(message, null, 2))

  return {
    output: output,
    executionTime: end - start,
  }
}
```

输出 :

```json
[
  [0, 0, 0, 0],
  [1, 0, 0, 0]
]
```

而如你所见,输出与我们加密的信息.txt中的原始消息相符:-)

* * *

### 证明

一旦你拥有所有必要的文物来证明(Witness、Proving Key、编译的Onnx模型和SRS),就可以使用 `prove` 方法. 实例应用中的方法使用 [处理GenProof按钮](https://github.com/zkonduit/ezkljs-engine/blob/main/app/Utils.tsx#164)

```typescript
import { prove, deserialize } from '@ezkljs/engine/web'

// This is the code for the button that triggers the
// generation of a proof.
export async function handleGenProofButton<T extends FileMapping>(
  files: T,
): Promise<Uint8ArrayResult> {
  const result = await convertFilesToFilesSer(files)

  const start = performance.now() // Start the timer

  let output = prove(
    result['data'],
    result['pk'],
    result['model'],
    result['srs'],
  )

  const end = performance.now() // End the timer

  let proof = deserialize(output)

  console.log(JSON.stringify(proof.proof, null, 2))
  console.log(JSON.stringify(proof.instances, null, 2))

  return {
    output: output,
    executionTime: end - start,
  }
}
```

输出 :

```json
"061557cfc629ce604da894831cd029d0444acf4f7e384d980e1ba7a5204f71a42a4c51e0a713df141416fd197367b56cfb3a56b1a5c7bd137f25046aa051665612f99bb5511db4b3d582f052ec82ed49356370e792ac669a8e940d3568285bbc10c78295369f844ada048e5efa897a227f05f68cc62706b145f88e3f943e559021dcd03884e21668db5cd925ce6807d6549e851709a7a3a8ac7b9666d1b2c0100d8a2682aa56d96a2ce8d0ae671e0c35c9c43e380308d246e7613122beca4f0828cdf8c9eebb0d9ee5a82a99a16c83ee5af9830a532a37c20e9f007d3f0312c200bd527998d6bbf40fab9e56bebd691ccc8131800a9b52851aea5019d06b736c1c44165d3c1992de958365a24f151606a4a50ffd121765d5283f7f809fa684432504487d8c48f12aeaf9caf30133f9ab1ec820e18db051b2ea31f2a10174514c2fe7a9f069c9913c3ee92a5deb9ab2fe9960d9a538ca00c3e0fb2cc457b899702aa74659de954943d3a5b589f82502693997178fa55a4f8677cd908e8ddcd9801cb371b84319454d1e8e1028f61bd355ae90689f6d3793444cb343cfe4ea637f2171d720686e0de1415d608c66ea9780c1abc0c884520e81a79ff8c11f5c339c2fb76fc9740cadb6eacee21f5c4adda72dce152d513c6562f3a7d23acfa83eff124945177df5433f7929730caae3622748a1ca86a0f73d838fcdb35f2a5686f02cba638cb1e5dff403519bf4813c60782f79cf08f2e583c490670e126a21213704fde2b3a4f9a8c418b3278bfe2f55ff47c6aa2015ded6752829b3cee375941315c98e5e31d0f4ec9b894ec51fee3941c438c974c51c41316de87b09be96f5f00fcfd4a5f556069e5798f49de750328088864927d4e4fe981550e5db1b981cff01ec4b2d03f63d3b4af7dd228f44c0b9b0ad4b72caf9bf7d4cd8c5b0ca51a9cd13fcda2a4cac59a8dd387ee6f503bbfd463ee379fb89aaa0cd6cffcbd95bb7ac1a1fa808ce43262d64c2fe355fdeae74ed366d27840dda8d0fe55ba6ffcef20e1be8475b82348ec92e6025c2496e11448d8b33377a360fca6d2918898a686c982db58e3bd42491992af5b4aea77e6991ae1f039f87bd3ed19b9ec74423956a3708d42d087723886ddd1c5486ed16610a123250c3c5e6014689d2767b4b4e22ef1e3af64dee3c29529c19be5081fdcb0a40171965ad5985dd942a836617f9dbbe012f27810b056ecc44636fadbc71943de4a20ffd3dc97238b0dbca16be8c10180d116ba8cc95eeb91d10d5e19f59303e984a845437a2c850021b2aa3c2141b3e020d1469095d76fb8298a870761fd2fcc2fc8057bf030f62ac3144a5770c60b0000000000000000000000000000000000000000000000000000000000000000025865fabaaa498f6b2042243bea2276cc7cdcf25e091f96a43eddaefd2a6a935013a3354557867640b7e902a005357c86c983aaee40bccb10eb8d6db6415915e1b477e066537576f70026752c4a27da71d491787297c18ba10f2a42db41b13df2d4096ced97df14e8c89a27bbc0e26b828dad7f5005e98e201992d3849611f520a0ed6030f402c363e526bf3607cced57998af94af4b6800ba87a685edbf742b202130ece182d26daefcfbe7412ff629407701d9adeff18446edaefd9abf6c98000000000000000000000000000000000000000000000000000000000000000000bda3a6a626469e211146d2f95c86d27f2a5b9d6d68f0a9670cee1243955c0f0ae946af8d44a1c2d448c9e024d2bbe96e5d2fea5d7915ca8eb481149bfadef20ecfee1f2b7d4a2ab4df06e00486bc1bd1c617f4d59a63fc2ec237594364f7510230555057f2f18e41e3d497f29bc9a30e2cbb17896f3e7f47ae0c010264b74501a6e3c81f4a937b66fc4baa9aa1cd062cdffdfecfef96f25b52f904c8b9d5b00fdd517551727930dd77dd45abee71f7aa50966d6e97aa4ba24831bacdd6354a18930a821ae32be9c13e66e4cb2a82c4d9e9ffd500c812c9a9a731a288d9c2361888a4e1b1a43df2fe0eca25a20025b1fccef7a4da7f808e59d050b652551fa100eeac3b40d1280d81aba6a3bfb433421427713de0d5d0b0a3639f1c7a4be64b2949b981ef4878eece723328d64def0ad4df93a2774d6a882ff0b6cd039239d627305afa05611ce6705dedef6c8cb221a1f251df9b3f1a04bb66ddc64a3feac51c01e60a44f75a12585a003ae3ddfdefa7568d8b30a31e2e5e8252aa9f34e476253ae4d74edd37762da29a7287184a2b7052d3b133721407aa36b5c9996e68c70b754ea01d61e33600675eb551a78f9fbb5b2abaf9a6b4c06b6cb2046b1eba8b2691a9fb51778a8bb703a618ff4406336431f38dd6927b254bc13428883ae6520e7139fcf91c3ec9c1e2cffbd588759f55308bdde05292d97988056e23a5814c1725005ba922bcadd7efbe9144f55628330b6d6d7e75d634b917e69b648ef2fc267660bd34097a148cbce8d2e9bfb96c57c8de474bd0e8de959f76f7eea00cfe05de16ea880ec32cf78d401a6210bec843dbdcc3b55df477887fce3b921ec76a019098130b9a6bcde1ea663d118e28e6b1878a5826679483ab408ed1a128561d0b62d261638e6f75f70b0406102cf15270c719be349cadec69638972ffc3dfed2afa94ed6db88dd30fc3c370115a1b317c6994f1afb1b74e1bf123b176f5665e2f419728174208207da99c5a6fbf8eaadecfbbd7d028866dcc737b8bff64b8c40bb3ca88b64c55a6b6ecafc5336c130eafc53d44a40e26a3b0bd8270bfa32c2e"

[
  [
    [
      0,
      0,
      0,
      0
    ],
    [
      0,
      0,
      0,
      0
    ],
    [
      0,
      0,
      0,
      0
    ],
    [
      0,
      0,
      0,
      0
    ]
  ]
]
```

* * *

### 校验

当证据生成时,您可以使用 `verify` 方法。 除了证明外,您还需要通过文件内容 校验密钥、电路设置和 srs 文件。 如果所有文物都正确,验证方法就会回归真实. 示例应用中所使用的方法 : [控件验证按钮](https://github.com/zkonduit/ezkljs-engine/blob/main/app/Utils.tsx#276)

```typescript
import { verify } from '@ezkljs/engine/web'

// This is the code for the button that triggers the
// verification of a proof.
export async function handleVerifyButton<T extends FileMapping>(
  files: T,
): Promise<VerifyResult> {
  const result = await convertFilesToFilesSer(files)

  const start = performance.now() // Start the timer

  let output = verify(
    result['proof'],
    result['vk'],
    result['circuitSettings'],
    result['srs'],
  )

  const end = performance.now() // End the timer

  console.log(output)

  return {
    output: output,
    executionTime: end - start,
  }
}
```

输出 :

```json
true
```

### 散开

我们还可以使用引擎来使用波塞冬散列函数来散列给定消息. 就像精灵加密和解密一样 我们需要把信息转换成 序列化的字段元素.

```typescript
import { hash, deserialize } from '@ezkljs/engine/web'

// This is the code for the button that triggers the
// posiedon hashing of a message.
export async function handleGenHashButton(message: File): Promise<Uint8Array> {
  const message_hash = await readUploadedFileAsBuffer(message)
  let output = poseidonHash(message_hash)
  let hash = deserialize(output)
  console.log(JSON.stringify(hash, null, 2))
  return output
}
```

如果您使用来自 elgamal 加密实例的同名信件. txt 文件, 您应该获得以下输出 :

```json
[
  [
    [
      "11803729404268464273",
      "978666863701269549",
      "3979600028898666103",
      "2559194768255192844"
    ]
  ]
]
```

## 常见问题

### @ezkljs/engine 是什么？

要安装 EZKL 引擎, 只需使用您最喜欢的软件包管理器 :

### 如何安装 @ezkljs/engine？

在项目目录运行 npm install @ezkljs/engine，或使用 pnpm add / yarn add / bun add。

### @ezkljs/engine 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @ezkljs/engine 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @ezkljs/engine 可以商用吗？

@ezkljs/engine 使用 未声明 许可。package\.json 没有声明许可证。没有许可证的代码默认保留全部权利，商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括，不构成法律意见，请以许可原文为准。

### @ezkljs/engine 的下载量有多少？

根据 npm 官方下载统计，@ezkljs/engine 在 2026/10/14 – 2026/11/12 这 30 天内被下载 2,592 次，日均约 86 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @ezkljs/engine 还在维护吗？

最新版本 22\.0\.1 发布于 2025/04/23（1\.6 年前）；至今共发布 116 个版本，其中过去 12 个月发布了 0 个；首次发布于 2023/08/11。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

