miniray 0.1.1

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/lib/browser.js ADDED
@@ -0,0 +1,177 @@
1
+ /**
2
+ * miniray - WGSL Minifier for WebGPU Shaders (Browser Build)
3
+ *
4
+ * Usage:
5
+ * import { initialize, minify } from 'miniray'
6
+ * await initialize({ wasmURL: '/miniray.wasm' })
7
+ * const result = minify(source, { minifyWhitespace: true })
8
+ */
9
+
10
+ (function (root, factory) {
11
+ if (typeof define === 'function' && define.amd) {
12
+ define([], factory);
13
+ } else if (typeof module === 'object' && module.exports) {
14
+ module.exports = factory();
15
+ } else {
16
+ root.miniray = factory();
17
+ }
18
+ }(typeof self !== 'undefined' ? self : this, function () {
19
+ 'use strict';
20
+
21
+ let _initialized = false;
22
+ let _initPromise = null;
23
+ let _go = null;
24
+
25
+ /**
26
+ * Initialize the WASM module.
27
+ * @param {Object} options
28
+ * @param {string|URL} [options.wasmURL] - URL to miniray.wasm
29
+ * @param {WebAssembly.Module} [options.wasmModule] - Pre-compiled module
30
+ * @returns {Promise<void>}
31
+ */
32
+ async function initialize(options) {
33
+ if (_initialized) {
34
+ return;
35
+ }
36
+ if (_initPromise) {
37
+ return _initPromise;
38
+ }
39
+
40
+ options = options || {};
41
+ const wasmURL = options.wasmURL;
42
+ const wasmModule = options.wasmModule;
43
+
44
+ if (!wasmURL && !wasmModule) {
45
+ throw new Error('Must provide either wasmURL or wasmModule');
46
+ }
47
+
48
+ _initPromise = _doInitialize(wasmURL, wasmModule);
49
+
50
+ try {
51
+ await _initPromise;
52
+ _initialized = true;
53
+ } catch (err) {
54
+ _initPromise = null;
55
+ throw err;
56
+ }
57
+ }
58
+
59
+ async function _doInitialize(wasmURL, wasmModule) {
60
+ // Load wasm_exec.js if Go is not defined
61
+ if (typeof Go === 'undefined') {
62
+ throw new Error(
63
+ 'Go runtime not found. Make sure to include wasm_exec.js before using miniray:\n' +
64
+ '<script src="wasm_exec.js"></script>'
65
+ );
66
+ }
67
+
68
+ _go = new Go();
69
+
70
+ let instance;
71
+ if (wasmModule) {
72
+ // Use pre-compiled module
73
+ instance = await WebAssembly.instantiate(wasmModule, _go.importObject);
74
+ } else {
75
+ // Fetch and instantiate
76
+ const url = wasmURL instanceof URL ? wasmURL.href : wasmURL;
77
+
78
+ if (typeof WebAssembly.instantiateStreaming === 'function') {
79
+ try {
80
+ const response = await fetch(url);
81
+ if (!response.ok) {
82
+ throw new Error(`Failed to fetch ${url}: ${response.status}`);
83
+ }
84
+ const result = await WebAssembly.instantiateStreaming(response, _go.importObject);
85
+ instance = result.instance;
86
+ } catch (err) {
87
+ // Fall back to arrayBuffer if streaming fails (e.g., wrong MIME type)
88
+ if (err.message && err.message.includes('MIME')) {
89
+ const response = await fetch(url);
90
+ const bytes = await response.arrayBuffer();
91
+ const result = await WebAssembly.instantiate(bytes, _go.importObject);
92
+ instance = result.instance;
93
+ } else {
94
+ throw err;
95
+ }
96
+ }
97
+ } else {
98
+ // Fallback for older browsers
99
+ const response = await fetch(url);
100
+ const bytes = await response.arrayBuffer();
101
+ const result = await WebAssembly.instantiate(bytes, _go.importObject);
102
+ instance = result.instance;
103
+ }
104
+ }
105
+
106
+ // Run the Go program (this sets up __miniray global)
107
+ _go.run(instance);
108
+
109
+ // Wait for __miniray to be available
110
+ await _waitForGlobal('__miniray', 1000);
111
+ }
112
+
113
+ function _waitForGlobal(name, timeout) {
114
+ return new Promise((resolve, reject) => {
115
+ const start = Date.now();
116
+ const check = () => {
117
+ if (typeof globalThis[name] !== 'undefined') {
118
+ resolve();
119
+ } else if (Date.now() - start > timeout) {
120
+ reject(new Error(`Timeout waiting for ${name} to be defined`));
121
+ } else {
122
+ setTimeout(check, 10);
123
+ }
124
+ };
125
+ check();
126
+ });
127
+ }
128
+
129
+ /**
130
+ * Minify WGSL source code.
131
+ * @param {string} source - WGSL source code
132
+ * @param {Object} [options] - Minification options
133
+ * @param {boolean} [options.minifyWhitespace=true] - Remove whitespace
134
+ * @param {boolean} [options.minifyIdentifiers=true] - Rename identifiers
135
+ * @param {boolean} [options.minifySyntax=true] - Optimize syntax
136
+ * @param {boolean} [options.mangleExternalBindings=false] - Mangle uniform/storage names
137
+ * @param {string[]} [options.keepNames] - Names to preserve
138
+ * @returns {Object} Result with code, errors, originalSize, minifiedSize
139
+ */
140
+ function minify(source, options) {
141
+ if (!_initialized) {
142
+ throw new Error('miniray not initialized. Call initialize() first.');
143
+ }
144
+
145
+ if (typeof source !== 'string') {
146
+ throw new Error('source must be a string');
147
+ }
148
+
149
+ return globalThis.__miniray.minify(source, options || {});
150
+ }
151
+
152
+ /**
153
+ * Check if initialized.
154
+ * @returns {boolean}
155
+ */
156
+ function isInitialized() {
157
+ return _initialized;
158
+ }
159
+
160
+ /**
161
+ * Get version.
162
+ * @returns {string}
163
+ */
164
+ function getVersion() {
165
+ if (!_initialized) {
166
+ return 'unknown';
167
+ }
168
+ return globalThis.__miniray.version;
169
+ }
170
+
171
+ return {
172
+ initialize: initialize,
173
+ minify: minify,
174
+ isInitialized: isInitialized,
175
+ get version() { return getVersion(); }
176
+ };
177
+ }));
package/lib/main.d.ts ADDED
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Options for WGSL minification.
3
+ */
4
+ export interface MinifyOptions {
5
+ /**
6
+ * Remove unnecessary whitespace and newlines.
7
+ * @default true
8
+ */
9
+ minifyWhitespace?: boolean;
10
+
11
+ /**
12
+ * Rename identifiers to shorter names.
13
+ * Entry points and API-facing declarations are preserved.
14
+ * @default true
15
+ */
16
+ minifyIdentifiers?: boolean;
17
+
18
+ /**
19
+ * Apply syntax-level optimizations (numeric literals, etc).
20
+ * @default true
21
+ */
22
+ minifySyntax?: boolean;
23
+
24
+ /**
25
+ * Rename uniform/storage variable declarations directly.
26
+ * When false (default), original names are preserved and short aliases are used.
27
+ * Set to true only if you don't use WebGPU's binding reflection APIs.
28
+ * @default false
29
+ */
30
+ mangleExternalBindings?: boolean;
31
+
32
+ /**
33
+ * Identifier names that should not be renamed.
34
+ */
35
+ keepNames?: string[];
36
+ }
37
+
38
+ /**
39
+ * Error information from minification.
40
+ */
41
+ export interface MinifyError {
42
+ /** Error message */
43
+ message: string;
44
+ /** Line number (1-indexed, 0 if unknown) */
45
+ line: number;
46
+ /** Column number (1-indexed, 0 if unknown) */
47
+ column: number;
48
+ }
49
+
50
+ /**
51
+ * Result of minification.
52
+ */
53
+ export interface MinifyResult {
54
+ /** Minified WGSL code */
55
+ code: string;
56
+ /** Errors encountered during minification */
57
+ errors: MinifyError[];
58
+ /** Size of input in bytes */
59
+ originalSize: number;
60
+ /** Size of output in bytes */
61
+ minifiedSize: number;
62
+ }
63
+
64
+ /**
65
+ * Options for initializing the WASM module.
66
+ */
67
+ export interface InitializeOptions {
68
+ /**
69
+ * URL or path to the wgslmin.wasm file.
70
+ * Required unless wasmModule is provided.
71
+ */
72
+ wasmURL?: string | URL;
73
+
74
+ /**
75
+ * Pre-compiled WebAssembly.Module.
76
+ * Use this to share a module across multiple instances.
77
+ */
78
+ wasmModule?: WebAssembly.Module;
79
+ }
80
+
81
+ /**
82
+ * Initialize the WASM module. Must be called before minify().
83
+ * @param options - Initialization options
84
+ */
85
+ export function initialize(options: InitializeOptions): Promise<void>;
86
+
87
+ /**
88
+ * Minify WGSL source code.
89
+ * @param source - WGSL source code to minify
90
+ * @param options - Minification options (defaults to full minification)
91
+ * @returns Minification result
92
+ */
93
+ export function minify(source: string, options?: MinifyOptions): MinifyResult;
94
+
95
+ /**
96
+ * Check if the WASM module is initialized.
97
+ */
98
+ export function isInitialized(): boolean;
99
+
100
+ /**
101
+ * Get the version of the minifier.
102
+ */
103
+ export const version: string;
package/lib/main.js ADDED
@@ -0,0 +1,152 @@
1
+ /**
2
+ * miniray - WGSL Minifier for WebGPU Shaders (Node.js Build)
3
+ *
4
+ * Usage:
5
+ * const { initialize, minify } = require('miniray')
6
+ * await initialize()
7
+ * const result = minify(source, { minifyWhitespace: true })
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+
15
+ let _initialized = false;
16
+ let _initPromise = null;
17
+ let _go = null;
18
+
19
+ /**
20
+ * Initialize the WASM module.
21
+ * @param {Object} options
22
+ * @param {string} [options.wasmURL] - Path to miniray.wasm
23
+ * @param {WebAssembly.Module} [options.wasmModule] - Pre-compiled module
24
+ * @returns {Promise<void>}
25
+ */
26
+ async function initialize(options) {
27
+ if (_initialized) {
28
+ return;
29
+ }
30
+ if (_initPromise) {
31
+ return _initPromise;
32
+ }
33
+
34
+ options = options || {};
35
+ let wasmURL = options.wasmURL;
36
+ const wasmModule = options.wasmModule;
37
+
38
+ // Default to miniray.wasm in the package directory
39
+ if (!wasmURL && !wasmModule) {
40
+ wasmURL = path.join(__dirname, '..', 'miniray.wasm');
41
+ }
42
+
43
+ _initPromise = _doInitialize(wasmURL, wasmModule);
44
+
45
+ try {
46
+ await _initPromise;
47
+ _initialized = true;
48
+ } catch (err) {
49
+ _initPromise = null;
50
+ throw err;
51
+ }
52
+ }
53
+
54
+ async function _doInitialize(wasmURL, wasmModule) {
55
+ // Set up globals required by wasm_exec.js
56
+ globalThis.require = require;
57
+ globalThis.fs = require('fs');
58
+ globalThis.path = require('path');
59
+ globalThis.TextEncoder = require('util').TextEncoder;
60
+ globalThis.TextDecoder = require('util').TextDecoder;
61
+ globalThis.performance ??= require('perf_hooks').performance;
62
+ globalThis.crypto ??= require('crypto');
63
+
64
+ // Load wasm_exec.js to set up Go runtime
65
+ const wasmExecPath = path.join(__dirname, '..', 'wasm_exec.js');
66
+ if (!fs.existsSync(wasmExecPath)) {
67
+ throw new Error(`wasm_exec.js not found at ${wasmExecPath}`);
68
+ }
69
+ require(wasmExecPath);
70
+
71
+ if (typeof Go === 'undefined') {
72
+ throw new Error('Go runtime not found after loading wasm_exec.js');
73
+ }
74
+
75
+ _go = new Go();
76
+
77
+ let instance;
78
+ if (wasmModule) {
79
+ instance = await WebAssembly.instantiate(wasmModule, _go.importObject);
80
+ } else {
81
+ const wasmPath = wasmURL instanceof URL ? wasmURL.pathname : wasmURL;
82
+ const wasmBuffer = fs.readFileSync(wasmPath);
83
+ const result = await WebAssembly.instantiate(wasmBuffer, _go.importObject);
84
+ instance = result.instance;
85
+ }
86
+
87
+ // Run the Go program (don't await - it runs in background)
88
+ _go.run(instance);
89
+
90
+ // Wait for __miniray to be available
91
+ await _waitForGlobal('__miniray', 1000);
92
+ }
93
+
94
+ function _waitForGlobal(name, timeout) {
95
+ return new Promise((resolve, reject) => {
96
+ const start = Date.now();
97
+ const check = () => {
98
+ if (typeof global[name] !== 'undefined') {
99
+ resolve();
100
+ } else if (Date.now() - start > timeout) {
101
+ reject(new Error(`Timeout waiting for ${name} to be defined`));
102
+ } else {
103
+ setTimeout(check, 10);
104
+ }
105
+ };
106
+ check();
107
+ });
108
+ }
109
+
110
+ /**
111
+ * Minify WGSL source code.
112
+ * @param {string} source - WGSL source code
113
+ * @param {Object} [options] - Minification options
114
+ * @returns {Object} Result
115
+ */
116
+ function minify(source, options) {
117
+ if (!_initialized) {
118
+ throw new Error('miniray not initialized. Call initialize() first.');
119
+ }
120
+
121
+ if (typeof source !== 'string') {
122
+ throw new Error('source must be a string');
123
+ }
124
+
125
+ return global.__miniray.minify(source, options || {});
126
+ }
127
+
128
+ /**
129
+ * Check if initialized.
130
+ * @returns {boolean}
131
+ */
132
+ function isInitialized() {
133
+ return _initialized;
134
+ }
135
+
136
+ /**
137
+ * Get version.
138
+ * @returns {string}
139
+ */
140
+ function getVersion() {
141
+ if (!_initialized) {
142
+ return 'unknown';
143
+ }
144
+ return global.__miniray.version;
145
+ }
146
+
147
+ module.exports = {
148
+ initialize,
149
+ minify,
150
+ isInitialized,
151
+ get version() { return getVersion(); }
152
+ };
package/miniray.wasm ADDED
Binary file
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "miniray",
3
+ "version": "0.1.1",
4
+ "description": "WGSL minifier for WebGPU shaders - WebAssembly build",
5
+ "main": "lib/main.js",
6
+ "module": "esm/browser.js",
7
+ "browser": {
8
+ "./lib/main.js": "./lib/browser.js"
9
+ },
10
+ "types": "lib/main.d.ts",
11
+ "bin": {
12
+ "miniray": "bin/miniray"
13
+ },
14
+ "exports": {
15
+ ".": {
16
+ "browser": {
17
+ "import": "./esm/browser.js",
18
+ "default": "./lib/browser.js"
19
+ },
20
+ "node": {
21
+ "import": "./esm/node.mjs",
22
+ "require": "./lib/main.js"
23
+ },
24
+ "default": "./lib/main.js"
25
+ },
26
+ "./wasm": "./miniray.wasm"
27
+ },
28
+ "files": [
29
+ "lib",
30
+ "esm",
31
+ "bin",
32
+ "miniray.wasm",
33
+ "wasm_exec.js"
34
+ ],
35
+ "keywords": [
36
+ "wgsl",
37
+ "webgpu",
38
+ "minifier",
39
+ "shader",
40
+ "wasm",
41
+ "webassembly",
42
+ "gpu",
43
+ "miniray"
44
+ ],
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "https://github.com/HugoDaniel/miniray"
48
+ },
49
+ "homepage": "https://github.com/HugoDaniel/miniray",
50
+ "license": "MIT",
51
+ "engines": {
52
+ "node": ">=16"
53
+ }
54
+ }