wasm-bindgen-lite 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Cargo.lock ADDED
@@ -0,0 +1,27 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "wasm-bindgen-lite"
7
+ version = "0.1.0"
8
+
9
+ [[package]]
10
+ name = "wasm-bindgen-lite-example-browser"
11
+ version = "0.1.0"
12
+
13
+ [[package]]
14
+ name = "wasm-bindgen-lite-example-node"
15
+ version = "0.1.0"
16
+
17
+ [[package]]
18
+ name = "wasm-bindgen-lite-example-offset-split"
19
+ version = "0.1.0"
20
+
21
+ [[package]]
22
+ name = "wasm-bindgen-lite-example-simd-sum"
23
+ version = "0.1.0"
24
+
25
+ [[package]]
26
+ name = "wasm-bindgen-lite-example-streaming-lines"
27
+ version = "0.1.0"
package/Cargo.toml ADDED
@@ -0,0 +1,23 @@
1
+ [package]
2
+ name = "wasm-bindgen-lite"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+ description = "CLI tool and runtime to build Rust crates into minimal, SIMD-optimized WASM packages with JS loaders"
6
+ license = "MIT"
7
+ repository = "https://github.com/addmaple/wasm-bindgen-lite"
8
+
9
+ [workspace]
10
+ members = ["examples/*"]
11
+
12
+ [lib]
13
+ crate-type = ["cdylib", "rlib"]
14
+
15
+ [dependencies]
16
+
17
+ [profile.release]
18
+ opt-level = "s"
19
+ lto = true
20
+ codegen-units = 1
21
+ panic = "abort"
22
+ strip = true
23
+
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 wasm-bindgen-lite contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,313 @@
1
+ # wasm-bindgen-lite
2
+
3
+ An ultra-minimal, high-performance CLI tool and runtime for building Rust WebAssembly packages.
4
+
5
+ `wasm-bindgen-lite` is designed for developers who want the performance of Rust WASM without the overhead and complexity of `wasm-bindgen`. It provides a thin, manual-memory-management layer that is perfect for performance-critical utilities like encoders, decoders, crypto, and data processing.
6
+
7
+ ## Why "Lite"?
8
+
9
+ Traditional `wasm-bindgen` generates a lot of glue code and often hides the underlying memory management. While convenient, it can introduce overhead and make it difficult to optimize data transfers.
10
+
11
+ **`wasm-bindgen-lite` gives you:**
12
+
13
+ - **Zero-cost ABI**: Uses standard `extern "C"` functions.
14
+ - **Manual Control**: Explicit `alloc` and `free` for maximum efficiency.
15
+ - **SIMD by Default**: Built-in support for SIMD detection and fallback.
16
+ - **Tiny Runtime**: A minimal JS wrapper (usually < 2KB) that works in Node.js and browsers.
17
+ - **Modern ESM**: Pure ESM output for modern build tools and runtimes.
18
+
19
+ ## Key Features
20
+
21
+ - 🚀 **SIMD Fallback**: Automatically compiles two versions of your WASM (baseline and SIMD). The runtime detects support and loads the fastest one.
22
+ - 📦 **Dual Loaders**: Supports standard `.wasm` files (best for caching) or inlined base64 (best for single-file distribution).
23
+ - 🔄 **Streaming Support**: Built-in integration with `TransformStream` for processing data chunks on the fly.
24
+ - 🛠️ **Configurable**: Simple `wasm-bindgen-lite.config.json` to define your exports and behavior.
25
+ - ⚡ **Optimized**: Integrated with `wasm-opt` for smallest possible binaries.
26
+
27
+ ## Quick Start
28
+
29
+ ### 1. Install
30
+
31
+ ```bash
32
+ npm install -D wasm-bindgen-lite
33
+ ```
34
+
35
+ ### 2. Prepare your Rust code
36
+
37
+ Expose `alloc_bytes` and `free_bytes` along with your functions. No `wasm-bindgen` dependency required!
38
+
39
+ ```rust
40
+ use std::alloc::{alloc, dealloc, Layout};
41
+ use std::mem;
42
+
43
+ #[no_mangle]
44
+ pub unsafe extern "C" fn alloc_bytes(len: usize) -> *mut u8 {
45
+ let layout = Layout::from_size_align(len, mem::align_of::<u8>()).unwrap();
46
+ alloc(layout)
47
+ }
48
+
49
+ #[no_mangle]
50
+ pub unsafe extern "C" fn free_bytes(ptr: *mut u8, len: usize) {
51
+ let layout = Layout::from_size_align(len, mem::align_of::<u8>()).unwrap();
52
+ dealloc(ptr, layout);
53
+ }
54
+
55
+ #[no_mangle]
56
+ pub unsafe extern "C" fn my_transform(
57
+ in_ptr: *const u8, in_len: usize,
58
+ out_ptr: *mut u8, _out_len: usize,
59
+ ) -> isize {
60
+ let input = std::slice::from_raw_parts(in_ptr, in_len);
61
+ let output = std::slice::from_raw_parts_mut(out_ptr, in_len);
62
+
63
+ for i in 0..in_len {
64
+ output[i] = input[i].wrapping_add(1);
65
+ }
66
+
67
+ in_len as isize
68
+ }
69
+ ```
70
+
71
+ ### 3. Build
72
+
73
+ Run the CLI to compile and generate JS loaders:
74
+
75
+ ```bash
76
+ rustup target add wasm32-unknown-unknown
77
+ npx wasm-bindgen-lite build --crate . --out ./wasm-dist
78
+ ```
79
+
80
+ ### 4. Use in JavaScript
81
+
82
+ If you've published your output as an npm package (e.g., `my-wasm-pkg`), consumers can simply import it. Modern runtimes and bundlers will automatically pick the correct version (Node vs Browser) via conditional exports.
83
+
84
+ ```javascript
85
+ import { init, my_transform } from 'my-wasm-pkg'
86
+
87
+ await init()
88
+
89
+ const input = new Uint8Array([1, 2, 3])
90
+ const output = my_transform(input)
91
+ console.log(output) // Uint8Array([2, 3, 4])
92
+ ```
93
+
94
+ ## Publishing & Automatic Export Configuration
95
+
96
+ When you build your project, `wasm-bindgen-lite` automatically detects your `package.json` and adds or updates the `exports` field to point to the generated artifacts.
97
+
98
+ This ensures that modern runtimes and bundlers automatically pick the correct version (Node vs Browser) via conditional exports.
99
+
100
+ ### Generated Exports Configuration
101
+
102
+ ```json
103
+ {
104
+ "exports": {
105
+ ".": {
106
+ "browser": "./wasm-dist/browser.js",
107
+ "node": "./wasm-dist/node.js",
108
+ "default": "./wasm-dist/node.js"
109
+ },
110
+ "./inline": {
111
+ "browser": "./wasm-dist/browser-inline.js",
112
+ "node": "./wasm-dist/node-inline.js",
113
+ "default": "./wasm-dist/node-inline.js"
114
+ }
115
+ }
116
+ }
117
+ ```
118
+
119
+ ### Import Examples
120
+
121
+ #### Standard (Automatic Environment Detection)
122
+
123
+ Used by Vite, Webpack, and Node.js.
124
+
125
+ ```javascript
126
+ import { init, my_transform } from 'my-wasm-pkg'
127
+ await init()
128
+ ```
129
+
130
+ #### Inline (Zero External Files)
131
+
132
+ Perfect for serverless or single-file distribution.
133
+
134
+ ```javascript
135
+ import { init, my_transform } from 'my-wasm-pkg/inline'
136
+ await init()
137
+ ```
138
+
139
+ #### CDN (jsDelivr, unpkg, etc.)
140
+
141
+ Because the browser loader uses modern `import.meta.url` resolution, it works out-of-the-box on CDNs. No extra configuration is needed.
142
+
143
+ ```javascript
144
+ import {
145
+ init,
146
+ my_transform,
147
+ } from 'https://cdn.jsdelivr.net/npm/my-wasm-pkg/wasm-dist/browser.js'
148
+ await init()
149
+ ```
150
+
151
+ > **Note**: For advanced users, there is a `wasmDelivery: { type: "jsdelivr" }` config option if you want to bundle the JS locally but fetch WASM binaries from a CDN (offloading).
152
+
153
+ ## Initialization Modes (`autoInit`)
154
+
155
+ The `autoInit` setting controls how and when the WASM module is instantiated.
156
+
157
+ ### 1. `off` (Default)
158
+
159
+ You must manually call `init()` and wait for it before calling any WASM functions.
160
+
161
+ ```javascript
162
+ import { init, process } from 'my-wasm-pkg'
163
+ await init()
164
+ const result = process(data) // Sync call
165
+ ```
166
+
167
+ ### 2. `lazy` (Automatic & Async)
168
+
169
+ The generated wrapper functions are `async`. They will automatically call `init()` on the first invocation.
170
+
171
+ ```javascript
172
+ import { process } from 'my-wasm-pkg'
173
+ const result = await process(data) // First call inits automatically
174
+ const result2 = await process(data2) // Subsequent calls use existing init
175
+ ```
176
+
177
+ ### 3. `eager` (Immediate)
178
+
179
+ `init()` is called immediately when the module is imported.
180
+
181
+ ```javascript
182
+ import { init, process } from 'my-wasm-pkg'
183
+ // init() is already running in the background
184
+ await init() // Ensure it's finished
185
+ const result = process(data)
186
+ ```
187
+
188
+ ## Custom JS Wrapper
189
+
190
+ You can provide a `js.custom` file to add high-level APIs. It has access to the internal `core.js` utilities.
191
+
192
+ **Example `src/wrapper.js`:**
193
+
194
+ ```javascript
195
+ import { createTransformStream } from './core.js'
196
+ export * from './core.js' // Re-export everything from core
197
+
198
+ const decoder = new TextDecoder()
199
+
200
+ export function createLineStream() {
201
+ // createTransformStream handles alloc/free for you
202
+ const wasmSplit = createTransformStream('splitLines')
203
+
204
+ return wasmSplit.readable.pipeThrough(
205
+ new TransformStream({
206
+ transform(chunk, controller) {
207
+ controller.enqueue(decoder.decode(chunk))
208
+ },
209
+ })
210
+ )
211
+ }
212
+ ```
213
+
214
+ Specify it in your config:
215
+
216
+ ```json
217
+ {
218
+ "js": { "custom": "src/wrapper.js" }
219
+ }
220
+ ```
221
+
222
+ ## Configuration (`wasm-bindgen-lite.config.json`)
223
+
224
+ ```json
225
+ {
226
+ "outDir": "wasm-dist",
227
+ "artifactBaseName": "mod",
228
+ "inline": true,
229
+ "targets": { "baseline": true, "simd": true },
230
+ "wasmOpt": { "mode": "auto", "args": ["-Oz"] },
231
+ "js": {
232
+ "emit": ["node", "browser", "inline"],
233
+ "custom": "src/wrapper.js"
234
+ },
235
+ "exports": [
236
+ {
237
+ "abi": "my_transform",
238
+ "name": "process",
239
+ "return": "bytes",
240
+ "reuseBuffer": true
241
+ }
242
+ ],
243
+ "autoInit": "lazy",
244
+ "stream": {
245
+ "enable": true,
246
+ "export": "process",
247
+ "delimiter": 10
248
+ },
249
+ "wasmDelivery": { "type": "relative" }
250
+ }
251
+ ```
252
+
253
+ ### Configuration Options
254
+
255
+ | Option | Description | Default |
256
+ | ----------------------- | ------------------------------------------------------------ | ------------- |
257
+ | `outDir` | Directory for generated files | `"dist"` |
258
+ | `artifactBaseName` | Base name for `.wasm` files | `"mod"` |
259
+ | `inline` | Whether to generate inline JS modules | `false` |
260
+ | `autoInit` | `"off"`, `"lazy"`, `"eager"` | `"off"` |
261
+ | `exports` | List of WASM functions to wrap | `[]` |
262
+ | `exports[].abi` | Name of the `extern "C"` function in Rust | required |
263
+ | `exports[].name` | Name of the exported JS function | same as `abi` |
264
+ | `exports[].return` | Return type: `bytes`, `f32`, `i32`, `u32`, etc. | `"bytes"` |
265
+ | `exports[].reuseBuffer` | If true, reuses the same memory buffer to reduce allocations | `false` |
266
+ | `stream.enable` | Generates a `createTransformStream()` helper | `false` |
267
+ | `js.custom` | Path to a custom JS file to include in the runtime | `null` |
268
+
269
+ ## Advanced Usage
270
+
271
+ ### SIMD Acceleration
272
+
273
+ `wasm-bindgen-lite` automatically compiles your Rust code with SIMD features enabled for the `.simd.wasm` target. The runtime detects support and picks the optimal binary.
274
+
275
+ ### Streaming Processing
276
+
277
+ Use `createTransformStream()` for high-performance data pipelines:
278
+
279
+ ```javascript
280
+ import { init, createTransformStream } from 'my-wasm-pkg'
281
+ await init()
282
+
283
+ const response = await fetch('data.bin')
284
+ const processed = response.body.pipeThrough(createTransformStream())
285
+ ```
286
+
287
+ ## CLI Reference
288
+
289
+ ```bash
290
+ wasm-bindgen-lite build [options]
291
+
292
+ Options:
293
+ --crate <path> Path to Rust crate (default: ".")
294
+ --out <path> Output directory
295
+ --release Build in release mode (default)
296
+ --debug Build in debug mode
297
+ --inline Generate inline JS loaders
298
+ --no-simd Disable SIMD build
299
+ --wasm-opt Enable wasm-opt (default)
300
+ --wasm-opt-args Custom args for wasm-opt
301
+ ```
302
+
303
+ ## Examples
304
+
305
+ - [node-basic](./examples/node-basic): Minimal Node.js setup.
306
+ - [browser-vite](./examples/browser-vite): Modern browser setup with Vite.
307
+ - [simd-sum](./examples/simd-sum): SIMD-accelerated array processing.
308
+ - [streaming-lines](./examples/streaming-lines): Streaming data with custom wrappers.
309
+ - [offset-split](./examples/offset-split): Advanced buffer management and complex ABI.
310
+
311
+ ## License
312
+
313
+ MIT
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env node
2
+ import { runBuild, runClean, printHelp } from '../src/cli/index.js'
3
+
4
+ function parseArgs(raw) {
5
+ const [command, ...rest] = raw
6
+ const opts = {}
7
+ const unknown = []
8
+
9
+ for (let i = 0; i < rest.length; i += 1) {
10
+ const arg = rest[i]
11
+ switch (arg) {
12
+ case '--crate':
13
+ opts.crate = rest[++i]
14
+ break
15
+ case '--out':
16
+ opts.out = rest[++i]
17
+ break
18
+ case '--config':
19
+ opts.configPath = rest[++i]
20
+ break
21
+ case '--release':
22
+ opts.release = true
23
+ break
24
+ case '--debug':
25
+ opts.release = false
26
+ break
27
+ case '--inline':
28
+ opts.inline = true
29
+ break
30
+ case '--no-inline':
31
+ opts.inline = false
32
+ break
33
+ case '--simd':
34
+ opts.simd = true
35
+ break
36
+ case '--no-simd':
37
+ opts.simd = false
38
+ break
39
+ case '--wasm-opt':
40
+ opts.wasmOptMode = 'on'
41
+ break
42
+ case '--no-wasm-opt':
43
+ opts.wasmOptMode = 'off'
44
+ break
45
+ case '--wasm-opt-args':
46
+ opts.wasmOptArgs = (rest[++i] || '').split(' ').filter(Boolean)
47
+ break
48
+ case '--update-package-json':
49
+ opts.updatePackageJson = true
50
+ break
51
+ case '--no-update-package-json':
52
+ opts.updatePackageJson = false
53
+ break
54
+ case '--help':
55
+ case '-h':
56
+ opts.help = true
57
+ break
58
+ default:
59
+ if (arg.startsWith('-')) {
60
+ unknown.push(arg)
61
+ } else {
62
+ unknown.push(arg)
63
+ }
64
+ break
65
+ }
66
+ }
67
+
68
+ return { command, opts, unknown }
69
+ }
70
+
71
+ async function main() {
72
+ const { command, opts, unknown } = parseArgs(process.argv.slice(2))
73
+
74
+ if (opts.help || !command || command === 'help') {
75
+ printHelp()
76
+ return
77
+ }
78
+
79
+ if (unknown.length) {
80
+ console.warn(`Ignoring unknown arguments: ${unknown.join(', ')}`)
81
+ }
82
+
83
+ if (command === 'build') {
84
+ await runBuild(opts)
85
+ return
86
+ }
87
+
88
+ if (command === 'clean') {
89
+ await runClean(opts)
90
+ return
91
+ }
92
+
93
+ console.error(`Unknown command: ${command}`)
94
+ printHelp()
95
+ process.exitCode = 1
96
+ }
97
+
98
+ main().catch((err) => {
99
+ console.error(err?.stack || err)
100
+ process.exitCode = 1
101
+ })
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "wasm-bindgen-lite",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "CLI tool to build Rust crates into minimal, SIMD-optimized WASM packages with JS loaders",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/addmaple/wasm-bindgen-lite.git"
9
+ },
10
+ "homepage": "https://github.com/addmaple/wasm-bindgen-lite#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/addmaple/wasm-bindgen-lite/issues"
13
+ },
14
+ "files": [
15
+ "bin/",
16
+ "src/",
17
+ "scripts/",
18
+ "Cargo.toml",
19
+ "Cargo.lock",
20
+ "README.md",
21
+ "LICENSE"
22
+ ],
23
+ "bin": {
24
+ "wasm-bindgen-lite": "./bin/wasm-bindgen-lite.js"
25
+ },
26
+ "main": "./src/cli/index.js",
27
+ "engines": {
28
+ "node": ">=20.0.0"
29
+ },
30
+ "scripts": {
31
+ "build": "node bin/wasm-bindgen-lite.js build --crate . --out dist --no-update-package-json",
32
+ "test": "cargo test && node scripts/test.js",
33
+ "test:examples": "./scripts/test-examples.sh",
34
+ "lint": "npm run lint:js && npm run lint:rust",
35
+ "lint:js": "eslint . && prettier --check .",
36
+ "lint:rust": "cargo clippy --workspace -- -D warnings",
37
+ "format": "prettier --write . && cargo fmt"
38
+ },
39
+ "keywords": [
40
+ "wasm",
41
+ "rust",
42
+ "simd",
43
+ "minimal",
44
+ "loader"
45
+ ],
46
+ "license": "MIT",
47
+ "devDependencies": {
48
+ "@eslint/js": "^9.39.2",
49
+ "base64-js": "^1.5.1",
50
+ "eslint": "^9.39.2",
51
+ "eslint-config-prettier": "^10.1.8",
52
+ "eslint-plugin-prettier": "^5.5.4",
53
+ "globals": "^16.5.0",
54
+ "prettier": "^3.7.4"
55
+ },
56
+ "exports": {
57
+ ".": "./src/cli/index.js"
58
+ }
59
+ }
@@ -0,0 +1,91 @@
1
+ import { execSync } from 'node:child_process'
2
+ import { mkdirSync, readFileSync, writeFileSync, copyFileSync } from 'node:fs'
3
+ import { join, dirname } from 'node:path'
4
+ import { fileURLToPath } from 'node:url'
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url))
7
+ const ROOT = join(__dirname, '..')
8
+ const DIST = join(ROOT, 'dist')
9
+ const SRC_JS = join(ROOT, 'src/js')
10
+
11
+ function run(cmd, env = {}) {
12
+ console.log(`> ${cmd}`)
13
+ execSync(cmd, { stdio: 'inherit', env: { ...process.env, ...env } })
14
+ }
15
+
16
+ // 1. Ensure target directory exists
17
+ mkdirSync(join(DIST, 'wasm'), { recursive: true })
18
+ mkdirSync(join(DIST, 'wasm-inline'), { recursive: true })
19
+
20
+ // 2. Build WASM (Baseline)
21
+ console.log('Building baseline WASM...')
22
+ run('cargo build --target wasm32-unknown-unknown --release')
23
+ const baselineWasm = join(
24
+ ROOT,
25
+ 'target/wasm32-unknown-unknown/release/wasm_bindgen_lite.wasm'
26
+ )
27
+
28
+ // 3. Build WASM (SIMD)
29
+ console.log('Building SIMD WASM...')
30
+ run('cargo build --target wasm32-unknown-unknown --release', {
31
+ RUSTFLAGS: '-C target-feature=+simd128',
32
+ })
33
+ const simdWasm = join(
34
+ ROOT,
35
+ 'target/wasm32-unknown-unknown/release/wasm_bindgen_lite.wasm'
36
+ )
37
+ // Note: Since we are building the same crate, we need to move the baseline first or build into different targets.
38
+ // Actually, cargo build will overwrite. Let's build baseline, move it, then build SIMD.
39
+
40
+ // Let's redo step 2 and 3 properly
41
+ console.log('Building baseline WASM...')
42
+ run('cargo build --target wasm32-unknown-unknown --release')
43
+ copyFileSync(baselineWasm, join(DIST, 'wasm/mod.base.wasm'))
44
+
45
+ console.log('Building SIMD WASM...')
46
+ run('cargo build --target wasm32-unknown-unknown --release', {
47
+ RUSTFLAGS: '-C target-feature=+simd128',
48
+ })
49
+ copyFileSync(simdWasm, join(DIST, 'wasm/mod.simd.wasm'))
50
+
51
+ // 4. Optimize (Optional - check for wasm-opt)
52
+ try {
53
+ run('wasm-opt --version')
54
+ console.log('Optimizing WASM...')
55
+ run(
56
+ `wasm-opt -Oz ${join(DIST, 'wasm/mod.base.wasm')} -o ${join(DIST, 'wasm/mod.base.wasm')}`
57
+ )
58
+ run(
59
+ `wasm-opt -Oz ${join(DIST, 'wasm/mod.simd.wasm')} -o ${join(DIST, 'wasm/mod.simd.wasm')}`
60
+ )
61
+ } catch (e) {
62
+ console.warn('wasm-opt not found, skipping optimization.')
63
+ }
64
+
65
+ // 5. Generate inline JS modules
66
+ function generateInline(name, wasmPath) {
67
+ const bytes = readFileSync(wasmPath)
68
+ const content = `// auto-generated\nexport const wasmBytes = new Uint8Array([${bytes.join(',')}]);\n`
69
+ writeFileSync(join(DIST, `wasm-inline/mod.${name}.wasm.js`), content)
70
+ }
71
+
72
+ console.log('Generating inline WASM modules...')
73
+ generateInline('base', join(DIST, 'wasm/mod.base.wasm'))
74
+ generateInline('simd', join(DIST, 'wasm/mod.simd.wasm'))
75
+
76
+ // 6. Copy JS files
77
+ console.log('Copying JS loaders...')
78
+ const jsFiles = [
79
+ 'core.js',
80
+ 'util.js',
81
+ 'browser.js',
82
+ 'node.js',
83
+ 'browser-inline.js',
84
+ 'node-inline.js',
85
+ ]
86
+
87
+ for (const f of jsFiles) {
88
+ copyFileSync(join(SRC_JS, f), join(DIST, f))
89
+ }
90
+
91
+ console.log('Build complete!')
@@ -0,0 +1,25 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Build the root package first
5
+ npm run build
6
+
7
+ for dir in examples/*; do
8
+ if [ -d "$dir" ]; then
9
+ echo "--- Testing $dir ---"
10
+ cd "$dir"
11
+ npm install
12
+ npm run build:wasm
13
+ if npm run test --if-present; then
14
+ echo "Tests passed for $dir"
15
+ fi
16
+ if npm run demo --if-present; then
17
+ echo "Demo passed for $dir"
18
+ fi
19
+ if [ -d "tests" ] && [ -f "playwright.config.js" ]; then
20
+ npx playwright install chromium
21
+ npm run test:pw
22
+ fi
23
+ cd ../..
24
+ fi
25
+ done