diff --git a/.changeset/lazy-wasi-warning.md b/.changeset/lazy-wasi-warning.md new file mode 100644 index 0000000..d7b81fb --- /dev/null +++ b/.changeset/lazy-wasi-warning.md @@ -0,0 +1,14 @@ +--- +'@offckb/cli': patch +--- + +fix(ckb-debugger): lazy-load WASI module to suppress ExperimentalWarning + +Convert static import of node:wasi to dynamic import with caching. +This prevents the ExperimentalWarning from being emitted when running +non-debugger commands like 'offckb accounts' or 'offckb config list'. + +The WASI module is now only loaded when debugger functionality is +actually executed. + +Fixes #405 diff --git a/src/tools/ckb-debugger-wasm.ts b/src/tools/ckb-debugger-wasm.ts index dd479a7..dfd1f3a 100644 --- a/src/tools/ckb-debugger-wasm.ts +++ b/src/tools/ckb-debugger-wasm.ts @@ -23,7 +23,6 @@ */ import * as fs from 'node:fs'; -import * as wasi from 'node:wasi'; import * as path from 'node:path'; /** @@ -60,6 +59,7 @@ export class CkbDebuggerWasi { private env: Record; private captureOutput: boolean; private wasm: WebAssembly.Module | null = null; + private static wasiModule: typeof import('node:wasi') | null = null; constructor(options: CkbDebuggerOptions = {}) { this.wasmPath = options.wasmPath || './ckb-debugger.wasm'; @@ -77,6 +77,17 @@ export class CkbDebuggerWasi { } } + private async getWasiModule(): Promise { + if (!CkbDebuggerWasi.wasiModule) { + try { + CkbDebuggerWasi.wasiModule = await import('node:wasi'); + } catch (_error) { + throw new Error('Failed to load WASI module. Node.js >= 20.0.0 is required for WASM debugger support.'); + } + } + return CkbDebuggerWasi.wasiModule; + } + private extractFilePathPreopens(args: string[]): Record { const additionalPreopens: Record = {}; for (let i = 0; i < args.length - 1; i++) { @@ -99,6 +110,7 @@ export class CkbDebuggerWasi { async run(args: string[] = [], preopens: Record = {}): Promise { await this.initialize(); + const wasiModule = await this.getWasiModule(); return new Promise((resolve, reject) => { try { @@ -136,7 +148,7 @@ export class CkbDebuggerWasi { // For output capture, we'll handle it differently since WASI expects file descriptors // We'll use the default stdout/stderr and capture via different means if needed - const wasihost = new wasi.WASI(wasiOptions); + const wasihost = new wasiModule.WASI(wasiOptions); // Instantiate the WebAssembly module WebAssembly.instantiate(this.wasm!, wasihost.getImportObject() as WebAssembly.Imports)