Skip to content

Commit 1ae678b

Browse files
OttoAllmendingerllm-git
andcommitted
feat(wasm-utxo): add ESM support as primary format with CJS fallback
This change migrates the package to use ESM as the primary format while maintaining compatibility with CommonJS consumers. Key changes: - Set "type": "module" in package.json - Configure dual ESM/CJS output with proper exports field - Add .js extensions to all imports for ESM compatibility - Update build scripts to create both ESM and CJS outputs - Configure tests to work with ESM imports - Add bundler compatibility tests for both ESM and CJS usage - Update mocha config for ESM testing Issue: esm-first.2 Co-authored-by: llm-git <[email protected]>
1 parent 56ba79a commit 1ae678b

27 files changed

+214
-96
lines changed

packages/wasm-utxo/.mocharc.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
{
2-
"extension": ["js", "ts"],
3-
"node-option": ["import=tsx"]
2+
"extensions": ["ts", "tsx", "js", "jsx"],
3+
"spec": ["test/**/*.ts"],
4+
"node-option": [
5+
"import=tsx/esm",
6+
"experimental-wasm-modules"
7+
]
48
}

packages/wasm-utxo/Makefile

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ define SHOW_WASM_SIZE
2323
@find $(1) -name "*.wasm" -exec gzip -k {} \;
2424
@find $(1) -name "*.wasm" -exec du -h {} \;
2525
@find $(1) -name "*.wasm.gz" -exec du -h {} \;
26+
@find $(1) -name "*.wasm.gz" -delete
2627
endef
2728

2829
define BUILD
@@ -35,15 +36,15 @@ endef
3536

3637
.PHONY: js/wasm/
3738
js/wasm/:
38-
$(call BUILD,$@,nodejs)
39+
$(call BUILD,$@,bundler)
3940

40-
.PHONY: dist/node/js/wasm/
41-
dist/node/js/wasm/:
42-
$(call BUILD,$@,nodejs)
41+
.PHONY: dist/esm/wasm/
42+
dist/esm/wasm/:
43+
$(call BUILD,$@,bundler)
4344

44-
.PHONY: dist/browser/js/wasm/
45-
dist/browser/js/wasm/:
46-
$(call BUILD,$@,browser)
45+
.PHONY: dist/cjs/wasm/
46+
dist/cjs/wasm/:
47+
$(call BUILD,$@,nodejs)
4748

4849
.PHONY: lint
4950
lint:
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Test script to verify CommonJS compatibility
3+
* Run with: node bundler-test/test-cjs-import.cjs
4+
*/
5+
6+
console.log('Testing CommonJS require() compatibility...\n');
7+
8+
// Use standard CommonJS require
9+
let wasmUtxo;
10+
try {
11+
wasmUtxo = require('../dist/cjs/index.js');
12+
} catch (error) {
13+
console.error('✗ require() failed:', error.message);
14+
process.exit(1);
15+
}
16+
17+
console.log('✓ require() successful from CJS context');
18+
console.log('✓ Available exports:', Object.keys(wasmUtxo).join(', '));
19+
20+
// Test that we can access the main APIs
21+
if (wasmUtxo.Descriptor) {
22+
console.log('✓ Descriptor API available');
23+
}
24+
if (wasmUtxo.Psbt) {
25+
console.log('✓ Psbt API available');
26+
}
27+
if (wasmUtxo.address) {
28+
console.log('✓ address namespace available');
29+
}
30+
if (wasmUtxo.fixedScriptWallet) {
31+
console.log('✓ fixedScriptWallet namespace available');
32+
}
33+
34+
// Try to use the Descriptor API
35+
try {
36+
const descriptor = wasmUtxo.Descriptor.fromString(
37+
'wpkh(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*)',
38+
'derivable'
39+
);
40+
console.log('✓ Descriptor.fromString() works');
41+
console.log(' Descriptor type:', descriptor.descType());
42+
} catch (err) {
43+
console.log('✗ Descriptor test failed:', err.message);
44+
process.exit(1);
45+
}
46+
47+
console.log('\n✅ All CJS compatibility tests passed!');
48+
console.log('\nCJS consumers can use standard require() with this package.');
49+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* Test script to verify ESM import works correctly
3+
* Run with: node --experimental-wasm-modules bundler-test/test-esm-import.mjs
4+
*/
5+
6+
import { Descriptor, Psbt, address, fixedScriptWallet } from '../dist/esm/index.js';
7+
8+
console.log('Testing ESM import...\n');
9+
10+
console.log('✓ ESM import successful');
11+
console.log('✓ Descriptor API available');
12+
console.log('✓ Psbt API available');
13+
console.log('✓ address namespace available');
14+
console.log('✓ fixedScriptWallet namespace available');
15+
16+
// Test that we can use the Descriptor API
17+
try {
18+
const descriptor = Descriptor.fromString(
19+
'wpkh(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*)',
20+
'derivable'
21+
);
22+
console.log('✓ Descriptor.fromString() works');
23+
console.log(' Descriptor type:', descriptor.descType());
24+
25+
// Test address derivation
26+
const derived = descriptor.atDerivationIndex(0);
27+
console.log('✓ Descriptor derivation works');
28+
console.log(' Script pubkey length:', derived.scriptPubkey().length);
29+
} catch (err) {
30+
console.log('✗ Descriptor test failed:', err.message);
31+
process.exit(1);
32+
}
33+
34+
console.log('\n✅ All ESM tests passed!');
35+
console.log('\nThis is the primary/recommended way to use this package.');
36+

packages/wasm-utxo/js/address.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { AddressNamespace } from "./wasm/wasm_utxo";
2-
import type { CoinName } from "./coinName";
1+
import { AddressNamespace } from "./wasm/wasm_utxo.js";
2+
import type { CoinName } from "./coinName.js";
33

44
/**
55
* Most coins only have one unambiguous address format (base58check and bech32/bech32m)

packages/wasm-utxo/js/ast/fromWasmNode.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { DescriptorNode, MiniscriptNode, TapTreeNode } from "./formatNode";
2-
import { Descriptor, Miniscript } from "../index";
1+
import { DescriptorNode, MiniscriptNode, TapTreeNode } from "./formatNode.js";
2+
import { Descriptor, Miniscript } from "../index.js";
33

44
function getSingleEntry(v: unknown): [string, unknown] {
55
if (typeof v === "object" && v) {

packages/wasm-utxo/js/ast/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
export * from "./formatNode";
2-
export * from "./fromWasmNode";
1+
export * from "./formatNode.js";
2+
export * from "./fromWasmNode.js";

packages/wasm-utxo/js/fixedScriptWallet.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { FixedScriptWalletNamespace } from "./wasm/wasm_utxo";
2-
import type { UtxolibName, UtxolibNetwork, UtxolibRootWalletKeys } from "./utxolibCompat";
3-
import type { CoinName } from "./coinName";
4-
import { Triple } from "./triple";
5-
import { AddressFormat } from "./address";
1+
import { FixedScriptWalletNamespace } from "./wasm/wasm_utxo.js";
2+
import type { UtxolibName, UtxolibNetwork, UtxolibRootWalletKeys } from "./utxolibCompat.js";
3+
import type { CoinName } from "./coinName.js";
4+
import { Triple } from "./triple.js";
5+
import { AddressFormat } from "./address.js";
66

77
export type NetworkName = UtxolibName | CoinName;
88

@@ -78,7 +78,7 @@ export type ParsedTransaction = {
7878
virtualSize: number;
7979
};
8080

81-
import { BitGoPsbt as WasmBitGoPsbt } from "./wasm/wasm_utxo";
81+
import { BitGoPsbt as WasmBitGoPsbt } from "./wasm/wasm_utxo.js";
8282

8383
export class BitGoPsbt {
8484
private constructor(private wasm: WasmBitGoPsbt) {}

packages/wasm-utxo/js/index.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
import * as wasm from "./wasm/wasm_utxo";
1+
import * as wasm from "./wasm/wasm_utxo.js";
22

33
// we need to access the wasm module here, otherwise webpack gets all weird
44
// and forgets to include it in the bundle
55
void wasm;
66

7-
export * as address from "./address";
8-
export * as ast from "./ast";
9-
export * as utxolibCompat from "./utxolibCompat";
10-
export * as fixedScriptWallet from "./fixedScriptWallet";
7+
export * as address from "./address.js";
8+
export * as ast from "./ast/index.js";
9+
export * as utxolibCompat from "./utxolibCompat.js";
10+
export * as fixedScriptWallet from "./fixedScriptWallet.js";
1111

12-
export type { CoinName } from "./coinName";
13-
export type { Triple } from "./triple";
14-
export type { AddressFormat } from "./address";
12+
export type { CoinName } from "./coinName.js";
13+
export type { Triple } from "./triple.js";
14+
export type { AddressFormat } from "./address.js";
1515

1616
export type DescriptorPkType = "derivable" | "definite" | "string";
1717

@@ -21,7 +21,7 @@ export type SignPsbtResult = {
2121
[inputIndex: number]: [pubkey: string][];
2222
};
2323

24-
declare module "./wasm/wasm_utxo" {
24+
declare module "./wasm/wasm_utxo.js" {
2525
interface WrapDescriptor {
2626
/** These are not the same types of nodes as in the ast module */
2727
node(): unknown;
@@ -48,6 +48,6 @@ declare module "./wasm/wasm_utxo" {
4848
}
4949
}
5050

51-
export { WrapDescriptor as Descriptor } from "./wasm/wasm_utxo";
52-
export { WrapMiniscript as Miniscript } from "./wasm/wasm_utxo";
53-
export { WrapPsbt as Psbt } from "./wasm/wasm_utxo";
51+
export { WrapDescriptor as Descriptor } from "./wasm/wasm_utxo.js";
52+
export { WrapMiniscript as Miniscript } from "./wasm/wasm_utxo.js";
53+
export { WrapPsbt as Psbt } from "./wasm/wasm_utxo.js";

packages/wasm-utxo/js/utxolibCompat.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import type { AddressFormat } from "./address";
2-
import { Triple } from "./triple";
3-
import { UtxolibCompatNamespace } from "./wasm/wasm_utxo";
1+
import type { AddressFormat } from "./address.js";
2+
import { Triple } from "./triple.js";
3+
import { UtxolibCompatNamespace } from "./wasm/wasm_utxo.js";
44

55
export type UtxolibName =
66
| "bitcoin"

0 commit comments

Comments
 (0)