motely-node 2.2.0 → 2.2.3

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.
Files changed (46) hide show
  1. package/README.md +70 -9
  2. package/_framework/Motely.80zooe1g1b.wasm +0 -0
  3. package/_framework/Motely.80zooe1g1b.wasm.br +0 -0
  4. package/_framework/Motely.80zooe1g1b.wasm.gz +0 -0
  5. package/_framework/Motely.SingleThread.qdb6metss2.wasm +0 -0
  6. package/_framework/Motely.SingleThread.qdb6metss2.wasm.br +0 -0
  7. package/_framework/Motely.SingleThread.qdb6metss2.wasm.gz +0 -0
  8. package/_framework/System.Private.CoreLib.t6vylij0to.wasm +0 -0
  9. package/_framework/System.Private.CoreLib.t6vylij0to.wasm.br +0 -0
  10. package/_framework/System.Private.CoreLib.t6vylij0to.wasm.gz +0 -0
  11. package/_framework/System.Runtime.InteropServices.JavaScript.4jnkqxblyl.wasm +0 -0
  12. package/_framework/System.Runtime.InteropServices.JavaScript.4jnkqxblyl.wasm.br +0 -0
  13. package/_framework/System.Runtime.InteropServices.JavaScript.4jnkqxblyl.wasm.gz +0 -0
  14. package/_framework/dotnet.js +11 -11
  15. package/_framework/dotnet.js.br +0 -0
  16. package/_framework/dotnet.js.gz +0 -0
  17. package/_framework/{dotnet.native.btc209xsl2.wasm → dotnet.native.ws3tq8jgzv.wasm} +0 -0
  18. package/_framework/dotnet.native.ws3tq8jgzv.wasm.br +0 -0
  19. package/_framework/{dotnet.native.btc209xsl2.wasm.gz → dotnet.native.ws3tq8jgzv.wasm.gz} +0 -0
  20. package/index.cjs +92 -0
  21. package/index.d.ts +11 -27
  22. package/index.js +43 -45
  23. package/jaml.schema.json +510 -0
  24. package/package.json +12 -8
  25. package/_framework/Motely.187ix5j7r4.wasm +0 -0
  26. package/_framework/Motely.187ix5j7r4.wasm.br +0 -0
  27. package/_framework/Motely.187ix5j7r4.wasm.gz +0 -0
  28. package/_framework/Motely.SingleThread.8ilcic7m8e.wasm +0 -0
  29. package/_framework/Motely.SingleThread.8ilcic7m8e.wasm.br +0 -0
  30. package/_framework/Motely.SingleThread.8ilcic7m8e.wasm.gz +0 -0
  31. package/_framework/Motely.SingleThread.i44l86ij06.wasm +0 -0
  32. package/_framework/Motely.SingleThread.i44l86ij06.wasm.br +0 -0
  33. package/_framework/Motely.SingleThread.i44l86ij06.wasm.gz +0 -0
  34. package/_framework/Motely.dlgz5zvozg.wasm +0 -0
  35. package/_framework/Motely.dlgz5zvozg.wasm.br +0 -0
  36. package/_framework/Motely.dlgz5zvozg.wasm.gz +0 -0
  37. package/_framework/System.Private.CoreLib.e4xpgjmfzj.wasm +0 -0
  38. package/_framework/System.Private.CoreLib.e4xpgjmfzj.wasm.br +0 -0
  39. package/_framework/System.Private.CoreLib.e4xpgjmfzj.wasm.gz +0 -0
  40. package/_framework/System.Runtime.InteropServices.JavaScript.60uq0t1ywb.wasm +0 -0
  41. package/_framework/System.Runtime.InteropServices.JavaScript.60uq0t1ywb.wasm.br +0 -0
  42. package/_framework/System.Runtime.InteropServices.JavaScript.60uq0t1ywb.wasm.gz +0 -0
  43. package/_framework/dotnet.native.btc209xsl2.wasm.br +0 -0
  44. package/_framework/dotnet.native.px7soob3pq.wasm +0 -0
  45. package/_framework/dotnet.native.px7soob3pq.wasm.br +0 -0
  46. package/_framework/dotnet.native.px7soob3pq.wasm.gz +0 -0
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # motely-node
2
2
 
3
- MotelyJAML for Node.js/V8 - Balatro seed analyzer and JAML filter engine.
3
+ MotelyJAML for **Node.js** Balatro seed analyzer and JAML filter engine.
4
4
 
5
- Uses the same .NET WASM runtime as the browser version, adapted for Node.js.
5
+ **High-level:** This package is for **Node.js only** (not WASI, not browser). The intended path is [*Develop a Node.js addon module in C# with .NET Native AOT*](https://microsoft.github.io/node-api-dotnet/scenarios/): a native `.node` binary that loads fast and does not depend on the .NET runtime. Today you can use either the **node-api-dotnet addon** (DLL + `addonPath`) or a **WASM fallback** (browser-style .NET WASM run in Node via `_framework`). Native AOT will produce a single platform-specific `.node` file for the addon path.
6
6
 
7
7
  ## Installation
8
8
 
@@ -12,11 +12,50 @@ npm install motely-node
12
12
 
13
13
  ## Requirements
14
14
 
15
- - Node.js >= 18.0.0
16
- - ESM support (type: "module")
15
+ - Node.js >= 24.0.0 (LTS)
16
+
17
+ ## CommonJS and ES
18
+
19
+ The package supports **both** CommonJS and ES modules. Use the one that matches your project.
20
+
21
+ **CommonJS**
22
+
23
+ ```javascript
24
+ const { loadMotely } = require('motely-node');
25
+
26
+ (async () => {
27
+ const motely = await loadMotely();
28
+ const caps = await motely.getCapabilities();
29
+ console.log('Runtime:', caps.runtime);
30
+ motely.dispose();
31
+ })();
32
+ ```
33
+
34
+ **ES**
35
+
36
+ ```javascript
37
+ import { loadMotely } from 'motely-node';
38
+
39
+ const motely = await loadMotely();
40
+ const caps = await motely.getCapabilities();
41
+ console.log('Runtime:', caps.runtime);
42
+ motely.dispose();
43
+ ```
44
+
45
+ ## Proof it works
46
+
47
+ From the package directory (after `dotnet publish` has populated `_framework/`):
48
+
49
+ ```bash
50
+ npm run prove
51
+ ```
52
+
53
+ Writes `prove-node-result.txt` with getCapabilities, validateJaml, and analyzeSeed results. Exit code 0 = OK.
17
54
 
18
55
  ## Usage
19
56
 
57
+ Initialize the runtime, then call the API. (Use [CommonJS or ES](#commonjs-and-es) imports as above.)
58
+
20
59
  ```javascript
21
60
  import { loadMotely } from 'motely-node';
22
61
 
@@ -68,10 +107,11 @@ motely.dispose();
68
107
 
69
108
  ### `loadMotely(options?): Promise<MotelyNodeApi>`
70
109
 
71
- Initialize the .NET WASM runtime.
110
+ Initialize Motely. Prefer **node-api-dotnet** addon when `addonPath` is set (in-process, faster); otherwise use .NET WASM.
72
111
 
73
- **Options:**
74
- - `frameworkPath?: string` - Custom path to the _framework directory (default: `./_framework`)
112
+ **Options:** ([reference](https://microsoft.github.io/node-api-dotnet/reference/js/))
113
+ - `addonPath?: string` - Path to `Motely.NodeAddon.dll`. Uses `node-api-dotnet` (optional dependency). Build from `Motely.NodeAddon` in the MotelyJAML repo.
114
+ - `frameworkPath?: string` - When using WASM, path to the `_framework` directory (default: `./_framework`)
75
115
 
76
116
  ### `MotelyNodeApi`
77
117
 
@@ -101,12 +141,33 @@ Start a JAML-based seed search.
101
141
 
102
142
  Cleanup and free resources.
103
143
 
144
+ ## Node API for .NET (addon)
145
+
146
+ For in-process, faster execution use the **node-api-dotnet** addon:
147
+
148
+ 1. Build the addon: from the MotelyJAML repo run `dotnet build Motely.NodeAddon/Motely.NodeAddon.csproj -c Release`.
149
+ 2. Install optional dependency: `npm install node-api-dotnet` (or it is listed as optionalDependency).
150
+ 3. Load with the DLL path:
151
+
152
+ ```javascript
153
+ import { loadMotely } from 'motely-node';
154
+ import path from 'node:path';
155
+ import { fileURLToPath } from 'node:url';
156
+
157
+ const dir = path.dirname(fileURLToPath(import.meta.url));
158
+ const motely = await loadMotely({
159
+ addonPath: path.join(dir, 'path-to-addon', 'Motely.NodeAddon.dll'),
160
+ });
161
+ ```
162
+
163
+ Same API; `runtime` in capabilities will be `"node-addon"`. Supports multi-threading. See [Node API for .NET](https://microsoft.github.io/node-api-dotnet/) and [.NET module for Node.js](https://microsoft.github.io/node-api-dotnet/scenarios/js-dotnet-module.html).
164
+
104
165
  ## Differences from Browser Version
105
166
 
106
- - Uses same .NET WASM runtime, adapted for Node.js
167
+ - Default: same .NET WASM runtime, adapted for Node.js. Optional: node-api-dotnet addon for in-process execution.
107
168
  - No browser-specific APIs (no DOM, no window object)
108
169
  - File system access via Node.js APIs
109
- - Multi-threading support (if Node.js supports SharedArrayBuffer)
170
+ - Multi-threading support (addon or WASM when Node supports SharedArrayBuffer)
110
171
  - Works in Node.js (Deno/Bun support may vary)
111
172
 
112
173
  ## License
@@ -4,7 +4,7 @@
4
4
  var e=!1;const t=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,8,1,6,0,6,64,25,11,11])),o=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,15,1,13,0,65,1,253,15,65,2,253,15,253,128,2,11])),n=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11])),r=Symbol.for("wasm promise_control");function i(e,t){let o=null;const n=new Promise((function(n,r){o={isDone:!1,promise:null,resolve:t=>{o.isDone||(o.isDone=!0,n(t),e&&e())},reject:e=>{o.isDone||(o.isDone=!0,r(e),t&&t())}}}));o.promise=n;const i=n;return i[r]=o,{promise:i,promise_control:o}}function s(e){return e[r]}function a(e){e&&function(e){return void 0!==e[r]}(e)||Be(!1,"Promise is not controllable")}const l="__mono_message__",c=["debug","log","trace","warn","info","error"],d="MONO_WASM: ";let u,f,m,g,p,h;function w(e){g=e}function b(e){if(Pe.diagnosticTracing){const t="function"==typeof e?e():e;console.debug(d+t)}}function y(e,...t){console.info(d+e,...t)}function v(e,...t){console.info(e,...t)}function E(e,...t){console.warn(d+e,...t)}function _(e,...t){if(t&&t.length>0&&t[0]&&"object"==typeof t[0]){if(t[0].silent)return;if(t[0].toString)return void console.error(d+e,t[0].toString())}console.error(d+e,...t)}function x(e,t,o){return function(...n){try{let r=n[0];if(void 0===r)r="undefined";else if(null===r)r="null";else if("function"==typeof r)r=r.toString();else if("string"!=typeof r)try{r=JSON.stringify(r)}catch(e){r=r.toString()}t(o?JSON.stringify({method:e,payload:r,arguments:n.slice(1)}):[e+r,...n.slice(1)])}catch(e){m.error(`proxyConsole failed: ${e}`)}}}function j(e,t,o){f=t,g=e,m={...t};const n=`${o}/console`.replace("https://","wss://").replace("http://","ws://");u=new WebSocket(n),u.addEventListener("error",A),u.addEventListener("close",S),function(){for(const e of c)f[e]=x(`console.${e}`,T,!0)}()}function R(e){let t=30;const o=()=>{u?0==u.bufferedAmount||0==t?(e&&v(e),function(){for(const e of c)f[e]=x(`console.${e}`,m.log,!1)}(),u.removeEventListener("error",A),u.removeEventListener("close",S),u.close(1e3,e),u=void 0):(t--,globalThis.setTimeout(o,100)):e&&m&&m.log(e)};o()}function T(e){u&&u.readyState===WebSocket.OPEN?u.send(e):m.log(e)}function A(e){m.error(`[${g}] proxy console websocket error: ${e}`,e)}function S(e){m.debug(`[${g}] proxy console websocket closed: ${e}`,e)}function D(){Pe.preferredIcuAsset=O(Pe.config);let e="invariant"==Pe.config.globalizationMode;if(!e)if(Pe.preferredIcuAsset)Pe.diagnosticTracing&&b("ICU data archive(s) available, disabling invariant mode");else{if("custom"===Pe.config.globalizationMode||"all"===Pe.config.globalizationMode||"sharded"===Pe.config.globalizationMode){const e="invariant globalization mode is inactive and no ICU data archives are available";throw _(`ERROR: ${e}`),new Error(e)}Pe.diagnosticTracing&&b("ICU data archive(s) not available, using invariant globalization mode"),e=!0,Pe.preferredIcuAsset=null}const t="DOTNET_SYSTEM_GLOBALIZATION_INVARIANT",o=Pe.config.environmentVariables;if(void 0===o[t]&&e&&(o[t]="1"),void 0===o.TZ)try{const e=Intl.DateTimeFormat().resolvedOptions().timeZone||null;e&&(o.TZ=e)}catch(e){y("failed to detect timezone, will fallback to UTC")}}function O(e){var t;if((null===(t=e.resources)||void 0===t?void 0:t.icu)&&"invariant"!=e.globalizationMode){const t=e.applicationCulture||(ke?globalThis.navigator&&globalThis.navigator.languages&&globalThis.navigator.languages[0]:Intl.DateTimeFormat().resolvedOptions().locale),o=e.resources.icu;let n=null;if("custom"===e.globalizationMode){if(o.length>=1)return o[0].name}else t&&"all"!==e.globalizationMode?"sharded"===e.globalizationMode&&(n=function(e){const t=e.split("-")[0];return"en"===t||["fr","fr-FR","it","it-IT","de","de-DE","es","es-ES"].includes(e)?"icudt_EFIGS.dat":["zh","ko","ja"].includes(t)?"icudt_CJK.dat":"icudt_no_CJK.dat"}(t)):n="icudt.dat";if(n)for(let e=0;e<o.length;e++){const t=o[e];if(t.virtualPath===n)return t.name}}return e.globalizationMode="invariant",null}(new Date).valueOf();const C=class{constructor(e){this.url=e}toString(){return this.url}};async function k(e,t){try{const o="function"==typeof globalThis.fetch;if(Se){const n=e.startsWith("file://");if(!n&&o)return globalThis.fetch(e,t||{credentials:"same-origin"});p||(h=Ne.require("url"),p=Ne.require("fs")),n&&(e=h.fileURLToPath(e));const r=await p.promises.readFile(e);return{ok:!0,headers:{length:0,get:()=>null},url:e,arrayBuffer:()=>r,json:()=>JSON.parse(r),text:()=>{throw new Error("NotImplementedException")}}}if(o)return globalThis.fetch(e,t||{credentials:"same-origin"});if("function"==typeof read)return{ok:!0,url:e,headers:{length:0,get:()=>null},arrayBuffer:()=>new Uint8Array(read(e,"binary")),json:()=>JSON.parse(read(e,"utf8")),text:()=>read(e,"utf8")}}catch(t){return{ok:!1,url:e,status:500,headers:{length:0,get:()=>null},statusText:"ERR28: "+t,arrayBuffer:()=>{throw t},json:()=>{throw t},text:()=>{throw t}}}throw new Error("No fetch implementation available")}function I(e){return"string"!=typeof e&&Be(!1,"url must be a string"),!M(e)&&0!==e.indexOf("./")&&0!==e.indexOf("../")&&globalThis.URL&&globalThis.document&&globalThis.document.baseURI&&(e=new URL(e,globalThis.document.baseURI).toString()),e}const U=/^[a-zA-Z][a-zA-Z\d+\-.]*?:\/\//,P=/[a-zA-Z]:[\\/]/;function M(e){return Se||Ie?e.startsWith("/")||e.startsWith("\\")||-1!==e.indexOf("///")||P.test(e):U.test(e)}let L,N=0;const $=[],z=[],W=new Map,F={"js-module-threads":!0,"js-module-runtime":!0,"js-module-dotnet":!0,"js-module-native":!0,"js-module-diagnostics":!0},B={...F,"js-module-library-initializer":!0},V={...F,dotnetwasm:!0,heap:!0,manifest:!0},q={...B,manifest:!0},H={...B,dotnetwasm:!0},J={dotnetwasm:!0,symbols:!0},Z={...B,dotnetwasm:!0,symbols:!0},Q={symbols:!0};function G(e){return!("icu"==e.behavior&&e.name!=Pe.preferredIcuAsset)}function K(e,t,o){null!=t||(t=[]),Be(1==t.length,`Expect to have one ${o} asset in resources`);const n=t[0];return n.behavior=o,X(n),e.push(n),n}function X(e){V[e.behavior]&&W.set(e.behavior,e)}function Y(e){Be(V[e],`Unknown single asset behavior ${e}`);const t=W.get(e);if(t&&!t.resolvedUrl)if(t.resolvedUrl=Pe.locateFile(t.name),F[t.behavior]){const e=ge(t);e?("string"!=typeof e&&Be(!1,"loadBootResource response for 'dotnetjs' type should be a URL string"),t.resolvedUrl=e):t.resolvedUrl=ce(t.resolvedUrl,t.behavior)}else if("dotnetwasm"!==t.behavior)throw new Error(`Unknown single asset behavior ${e}`);return t}function ee(e){const t=Y(e);return Be(t,`Single asset for ${e} not found`),t}let te=!1;async function oe(){if(!te){te=!0,Pe.diagnosticTracing&&b("mono_download_assets");try{const e=[],t=[],o=(e,t)=>{!Z[e.behavior]&&G(e)&&Pe.expected_instantiated_assets_count++,!H[e.behavior]&&G(e)&&(Pe.expected_downloaded_assets_count++,t.push(se(e)))};for(const t of $)o(t,e);for(const e of z)o(e,t);Pe.allDownloadsQueued.promise_control.resolve(),Promise.all([...e,...t]).then((()=>{Pe.allDownloadsFinished.promise_control.resolve()})).catch((e=>{throw Pe.err("Error in mono_download_assets: "+e),Xe(1,e),e})),await Pe.runtimeModuleLoaded.promise;const n=async e=>{const t=await e;if(t.buffer){if(!Z[t.behavior]){t.buffer&&"object"==typeof t.buffer||Be(!1,"asset buffer must be array-like or buffer-like or promise of these"),"string"!=typeof t.resolvedUrl&&Be(!1,"resolvedUrl must be string");const e=t.resolvedUrl,o=await t.buffer,n=new Uint8Array(o);pe(t),await Ue.beforeOnRuntimeInitialized.promise,Ue.instantiate_asset(t,e,n)}}else J[t.behavior]?("symbols"===t.behavior&&(await Ue.instantiate_symbols_asset(t),pe(t)),J[t.behavior]&&++Pe.actual_downloaded_assets_count):(t.isOptional||Be(!1,"Expected asset to have the downloaded buffer"),!H[t.behavior]&&G(t)&&Pe.expected_downloaded_assets_count--,!Z[t.behavior]&&G(t)&&Pe.expected_instantiated_assets_count--)},r=[],i=[];for(const t of e)r.push(n(t));for(const e of t)i.push(n(e));Promise.all(r).then((()=>{Ce||Ue.coreAssetsInMemory.promise_control.resolve()})).catch((e=>{throw Pe.err("Error in mono_download_assets: "+e),Xe(1,e),e})),Promise.all(i).then((async()=>{Ce||(await Ue.coreAssetsInMemory.promise,Ue.allAssetsInMemory.promise_control.resolve())})).catch((e=>{throw Pe.err("Error in mono_download_assets: "+e),Xe(1,e),e}))}catch(e){throw Pe.err("Error in mono_download_assets: "+e),e}}}let ne=!1;function re(){if(ne)return;ne=!0;const e=Pe.config,t=[];if(e.assets)for(const t of e.assets)"object"!=typeof t&&Be(!1,`asset must be object, it was ${typeof t} : ${t}`),"string"!=typeof t.behavior&&Be(!1,"asset behavior must be known string"),"string"!=typeof t.name&&Be(!1,"asset name must be string"),t.resolvedUrl&&"string"!=typeof t.resolvedUrl&&Be(!1,"asset resolvedUrl could be string"),t.hash&&"string"!=typeof t.hash&&Be(!1,"asset resolvedUrl could be string"),t.pendingDownload&&"object"!=typeof t.pendingDownload&&Be(!1,"asset pendingDownload could be object"),t.isCore?$.push(t):z.push(t),X(t);else if(e.resources){const o=e.resources;o.wasmNative||Be(!1,"resources.wasmNative must be defined"),o.jsModuleNative||Be(!1,"resources.jsModuleNative must be defined"),o.jsModuleRuntime||Be(!1,"resources.jsModuleRuntime must be defined"),K(z,o.wasmNative,"dotnetwasm"),K(t,o.jsModuleNative,"js-module-native"),K(t,o.jsModuleRuntime,"js-module-runtime"),o.jsModuleDiagnostics&&K(t,o.jsModuleDiagnostics,"js-module-diagnostics");const n=(e,t,o)=>{const n=e;n.behavior=t,o?(n.isCore=!0,$.push(n)):z.push(n)};if(o.coreAssembly)for(let e=0;e<o.coreAssembly.length;e++)n(o.coreAssembly[e],"assembly",!0);if(o.assembly)for(let e=0;e<o.assembly.length;e++)n(o.assembly[e],"assembly",!o.coreAssembly);if(0!=e.debugLevel&&Pe.isDebuggingSupported()){if(o.corePdb)for(let e=0;e<o.corePdb.length;e++)n(o.corePdb[e],"pdb",!0);if(o.pdb)for(let e=0;e<o.pdb.length;e++)n(o.pdb[e],"pdb",!o.corePdb)}if(e.loadAllSatelliteResources&&o.satelliteResources)for(const e in o.satelliteResources)for(let t=0;t<o.satelliteResources[e].length;t++){const r=o.satelliteResources[e][t];r.culture=e,n(r,"resource",!o.coreAssembly)}if(o.coreVfs)for(let e=0;e<o.coreVfs.length;e++)n(o.coreVfs[e],"vfs",!0);if(o.vfs)for(let e=0;e<o.vfs.length;e++)n(o.vfs[e],"vfs",!o.coreVfs);const r=O(e);if(r&&o.icu)for(let e=0;e<o.icu.length;e++){const t=o.icu[e];t.name===r&&n(t,"icu",!1)}if(o.wasmSymbols)for(let e=0;e<o.wasmSymbols.length;e++)n(o.wasmSymbols[e],"symbols",!1)}if(e.appsettings)for(let t=0;t<e.appsettings.length;t++){const o=e.appsettings[t],n=he(o);"appsettings.json"!==n&&n!==`appsettings.${e.applicationEnvironment}.json`||z.push({name:o,behavior:"vfs",cache:"no-cache",useCredentials:!0})}e.assets=[...$,...z,...t]}async function ie(e){const t=await se(e);return await t.pendingDownloadInternal.response,t.buffer}async function se(e){try{return await ae(e)}catch(t){if(!Pe.enableDownloadRetry)throw t;if(Ie||Se)throw t;if(e.pendingDownload&&e.pendingDownloadInternal==e.pendingDownload)throw t;if(e.resolvedUrl&&-1!=e.resolvedUrl.indexOf("file://"))throw t;if(t&&404==t.status)throw t;e.pendingDownloadInternal=void 0,await Pe.allDownloadsQueued.promise;try{return Pe.diagnosticTracing&&b(`Retrying download '${e.name}'`),await ae(e)}catch(t){return e.pendingDownloadInternal=void 0,await new Promise((e=>globalThis.setTimeout(e,100))),Pe.diagnosticTracing&&b(`Retrying download (2) '${e.name}' after delay`),await ae(e)}}}async function ae(e){for(;L;)await L.promise;try{++N,N==Pe.maxParallelDownloads&&(Pe.diagnosticTracing&&b("Throttling further parallel downloads"),L=i());const t=await async function(e){if(e.pendingDownload&&(e.pendingDownloadInternal=e.pendingDownload),e.pendingDownloadInternal&&e.pendingDownloadInternal.response)return e.pendingDownloadInternal.response;if(e.buffer){const t=await e.buffer;return e.resolvedUrl||(e.resolvedUrl="undefined://"+e.name),e.pendingDownloadInternal={url:e.resolvedUrl,name:e.name,response:Promise.resolve({ok:!0,arrayBuffer:()=>t,json:()=>JSON.parse(new TextDecoder("utf-8").decode(t)),text:()=>{throw new Error("NotImplementedException")},headers:{get:()=>{}}})},e.pendingDownloadInternal.response}const t=e.loadRemote&&Pe.config.remoteSources?Pe.config.remoteSources:[""];let o;for(let n of t){n=n.trim(),"./"===n&&(n="");const t=le(e,n);e.name===t?Pe.diagnosticTracing&&b(`Attempting to download '${t}'`):Pe.diagnosticTracing&&b(`Attempting to download '${t}' for ${e.name}`);try{e.resolvedUrl=t;const n=fe(e);if(e.pendingDownloadInternal=n,o=await n.response,!o||!o.ok)continue;return o}catch(e){o||(o={ok:!1,url:t,status:0,statusText:""+e});continue}}const n=e.isOptional||e.name.match(/\.pdb$/)&&Pe.config.ignorePdbLoadErrors;if(o||Be(!1,`Response undefined ${e.name}`),!n){const t=new Error(`download '${o.url}' for ${e.name} failed ${o.status} ${o.statusText}`);throw t.status=o.status,t}y(`optional download '${o.url}' for ${e.name} failed ${o.status} ${o.statusText}`)}(e);return t?(J[e.behavior]||(e.buffer=await t.arrayBuffer(),++Pe.actual_downloaded_assets_count),e):e}finally{if(--N,L&&N==Pe.maxParallelDownloads-1){Pe.diagnosticTracing&&b("Resuming more parallel downloads");const e=L;L=void 0,e.promise_control.resolve()}}}function le(e,t){let o;return null==t&&Be(!1,`sourcePrefix must be provided for ${e.name}`),e.resolvedUrl?o=e.resolvedUrl:(o=""===t?"assembly"===e.behavior||"pdb"===e.behavior?e.name:"resource"===e.behavior&&e.culture&&""!==e.culture?`${e.culture}/${e.name}`:e.name:t+e.name,o=ce(Pe.locateFile(o),e.behavior)),o&&"string"==typeof o||Be(!1,"attemptUrl need to be path or url string"),o}function ce(e,t){return Pe.modulesUniqueQuery&&q[t]&&(e+=Pe.modulesUniqueQuery),e}let de=0;const ue=new Set;function fe(e){try{e.resolvedUrl||Be(!1,"Request's resolvedUrl must be set");const t=function(e){let t=e.resolvedUrl;if(Pe.loadBootResource){const o=ge(e);if(o instanceof Promise)return o;"string"==typeof o&&(t=o)}const o={};return e.cache?o.cache=e.cache:Pe.config.disableNoCacheFetch||(o.cache="no-cache"),e.useCredentials?o.credentials="include":!Pe.config.disableIntegrityCheck&&e.hash&&(o.integrity=e.hash),Pe.fetch_like(t,o)}(e),o={name:e.name,url:e.resolvedUrl,response:t};return ue.add(e.name),o.response.then((()=>{"assembly"==e.behavior&&Pe.loadedAssemblies.push(e.name),de++,Pe.onDownloadResourceProgress&&Pe.onDownloadResourceProgress(de,ue.size)})),o}catch(t){const o={ok:!1,url:e.resolvedUrl,status:500,statusText:"ERR29: "+t,arrayBuffer:()=>{throw t},json:()=>{throw t}};return{name:e.name,url:e.resolvedUrl,response:Promise.resolve(o)}}}const me={resource:"assembly",assembly:"assembly",pdb:"pdb",icu:"globalization",vfs:"configuration",manifest:"manifest",dotnetwasm:"dotnetwasm","js-module-dotnet":"dotnetjs","js-module-native":"dotnetjs","js-module-runtime":"dotnetjs","js-module-threads":"dotnetjs"};function ge(e){var t;if(Pe.loadBootResource){const o=null!==(t=e.hash)&&void 0!==t?t:"",n=e.resolvedUrl,r=me[e.behavior];if(r){const t=Pe.loadBootResource(r,e.name,n,o,e.behavior);return"string"==typeof t?I(t):t}}}function pe(e){e.pendingDownloadInternal=null,e.pendingDownload=null,e.buffer=null,e.moduleExports=null}function he(e){let t=e.lastIndexOf("/");return t>=0&&t++,e.substring(t)}async function we(e){e&&await Promise.all((null!=e?e:[]).map((e=>async function(e){try{const t=e.name;if(!e.moduleExports){const o=ce(Pe.locateFile(t),"js-module-library-initializer");Pe.diagnosticTracing&&b(`Attempting to import '${o}' for ${e}`),e.moduleExports=await import(/*! webpackIgnore: true */o)}Pe.libraryInitializers.push({scriptName:t,exports:e.moduleExports})}catch(t){E(`Failed to import library initializer '${e}': ${t}`)}}(e))))}async function be(e,t){if(!Pe.libraryInitializers)return;const o=[];for(let n=0;n<Pe.libraryInitializers.length;n++){const r=Pe.libraryInitializers[n];r.exports[e]&&o.push(ye(r.scriptName,e,(()=>r.exports[e](...t))))}await Promise.all(o)}async function ye(e,t,o){try{await o()}catch(o){throw E(`Failed to invoke '${t}' on library initializer '${e}': ${o}`),Xe(1,o),o}}function ve(e,t){if(e===t)return e;const o={...t};return void 0!==o.assets&&o.assets!==e.assets&&(o.assets=[...e.assets||[],...o.assets||[]]),void 0!==o.resources&&(o.resources=_e(e.resources||{assembly:[],jsModuleNative:[],jsModuleRuntime:[],wasmNative:[]},o.resources)),void 0!==o.environmentVariables&&(o.environmentVariables={...e.environmentVariables||{},...o.environmentVariables||{}}),void 0!==o.runtimeOptions&&o.runtimeOptions!==e.runtimeOptions&&(o.runtimeOptions=[...e.runtimeOptions||[],...o.runtimeOptions||[]]),Object.assign(e,o)}function Ee(e,t){if(e===t)return e;const o={...t};return o.config&&(e.config||(e.config={}),o.config=ve(e.config,o.config)),Object.assign(e,o)}function _e(e,t){if(e===t)return e;const o={...t};return void 0!==o.coreAssembly&&(o.coreAssembly=[...e.coreAssembly||[],...o.coreAssembly||[]]),void 0!==o.assembly&&(o.assembly=[...e.assembly||[],...o.assembly||[]]),void 0!==o.lazyAssembly&&(o.lazyAssembly=[...e.lazyAssembly||[],...o.lazyAssembly||[]]),void 0!==o.corePdb&&(o.corePdb=[...e.corePdb||[],...o.corePdb||[]]),void 0!==o.pdb&&(o.pdb=[...e.pdb||[],...o.pdb||[]]),void 0!==o.jsModuleWorker&&(o.jsModuleWorker=[...e.jsModuleWorker||[],...o.jsModuleWorker||[]]),void 0!==o.jsModuleNative&&(o.jsModuleNative=[...e.jsModuleNative||[],...o.jsModuleNative||[]]),void 0!==o.jsModuleDiagnostics&&(o.jsModuleDiagnostics=[...e.jsModuleDiagnostics||[],...o.jsModuleDiagnostics||[]]),void 0!==o.jsModuleRuntime&&(o.jsModuleRuntime=[...e.jsModuleRuntime||[],...o.jsModuleRuntime||[]]),void 0!==o.wasmSymbols&&(o.wasmSymbols=[...e.wasmSymbols||[],...o.wasmSymbols||[]]),void 0!==o.wasmNative&&(o.wasmNative=[...e.wasmNative||[],...o.wasmNative||[]]),void 0!==o.icu&&(o.icu=[...e.icu||[],...o.icu||[]]),void 0!==o.satelliteResources&&(o.satelliteResources=function(e,t){if(e===t)return e;for(const o in t)e[o]=[...e[o]||[],...t[o]||[]];return e}(e.satelliteResources||{},o.satelliteResources||{})),void 0!==o.modulesAfterConfigLoaded&&(o.modulesAfterConfigLoaded=[...e.modulesAfterConfigLoaded||[],...o.modulesAfterConfigLoaded||[]]),void 0!==o.modulesAfterRuntimeReady&&(o.modulesAfterRuntimeReady=[...e.modulesAfterRuntimeReady||[],...o.modulesAfterRuntimeReady||[]]),void 0!==o.extensions&&(o.extensions={...e.extensions||{},...o.extensions||{}}),void 0!==o.vfs&&(o.vfs=[...e.vfs||[],...o.vfs||[]]),Object.assign(e,o)}function xe(){const e=Pe.config;if(e.environmentVariables=e.environmentVariables||{},e.runtimeOptions=e.runtimeOptions||[],e.resources=e.resources||{assembly:[],jsModuleNative:[],jsModuleWorker:[],jsModuleRuntime:[],wasmNative:[],vfs:[],satelliteResources:{}},e.assets){Pe.diagnosticTracing&&b("config.assets is deprecated, use config.resources instead");for(const t of e.assets){const o={};switch(t.behavior){case"assembly":o.assembly=[t];break;case"pdb":o.pdb=[t];break;case"resource":o.satelliteResources={},o.satelliteResources[t.culture]=[t];break;case"icu":o.icu=[t];break;case"symbols":o.wasmSymbols=[t];break;case"vfs":o.vfs=[t];break;case"dotnetwasm":o.wasmNative=[t];break;case"js-module-threads":o.jsModuleWorker=[t];break;case"js-module-runtime":o.jsModuleRuntime=[t];break;case"js-module-native":o.jsModuleNative=[t];break;case"js-module-diagnostics":o.jsModuleDiagnostics=[t];break;case"js-module-dotnet":break;default:throw new Error(`Unexpected behavior ${t.behavior} of asset ${t.name}`)}_e(e.resources,o)}}e.debugLevel,e.applicationEnvironment||(e.applicationEnvironment="Production"),e.applicationCulture&&(e.environmentVariables.LANG=`${e.applicationCulture}.UTF-8`),Ue.diagnosticTracing=Pe.diagnosticTracing=!!e.diagnosticTracing,Ue.waitForDebugger=e.waitForDebugger,Pe.maxParallelDownloads=e.maxParallelDownloads||Pe.maxParallelDownloads,Pe.enableDownloadRetry=void 0!==e.enableDownloadRetry?e.enableDownloadRetry:Pe.enableDownloadRetry}let je=!1;async function Re(e){var t;if(je)return void await Pe.afterConfigLoaded.promise;let o;try{if(e.configSrc||Pe.config&&0!==Object.keys(Pe.config).length&&(Pe.config.assets||Pe.config.resources)||(e.configSrc="dotnet.boot.js"),o=e.configSrc,je=!0,o&&(Pe.diagnosticTracing&&b("mono_wasm_load_config"),await async function(e){const t=e.configSrc,o=Pe.locateFile(t);let n=null;void 0!==Pe.loadBootResource&&(n=Pe.loadBootResource("manifest",t,o,"","manifest"));let r,i=null;if(n)if("string"==typeof n)n.includes(".json")?(i=await s(I(n)),r=await Ae(i)):r=(await import(I(n))).config;else{const e=await n;"function"==typeof e.json?(i=e,r=await Ae(i)):r=e.config}else o.includes(".json")?(i=await s(ce(o,"manifest")),r=await Ae(i)):r=(await import(ce(o,"manifest"))).config;function s(e){return Pe.fetch_like(e,{method:"GET",credentials:"include",cache:"no-cache"})}Pe.config.applicationEnvironment&&(r.applicationEnvironment=Pe.config.applicationEnvironment),ve(Pe.config,r)}(e)),xe(),await we(null===(t=Pe.config.resources)||void 0===t?void 0:t.modulesAfterConfigLoaded),await be("onRuntimeConfigLoaded",[Pe.config]),e.onConfigLoaded)try{await e.onConfigLoaded(Pe.config,Le),xe()}catch(e){throw _("onConfigLoaded() failed",e),e}xe(),Pe.afterConfigLoaded.promise_control.resolve(Pe.config)}catch(t){const n=`Failed to load config file ${o} ${t} ${null==t?void 0:t.stack}`;throw Pe.config=e.config=Object.assign(Pe.config,{message:n,error:t,isError:!0}),Xe(1,new Error(n)),t}}function Te(){return!!globalThis.navigator&&(Pe.isChromium||Pe.isFirefox)}async function Ae(e){const t=Pe.config,o=await e.json();t.applicationEnvironment||o.applicationEnvironment||(o.applicationEnvironment=e.headers.get("Blazor-Environment")||e.headers.get("DotNet-Environment")||void 0),o.environmentVariables||(o.environmentVariables={});const n=e.headers.get("DOTNET-MODIFIABLE-ASSEMBLIES");n&&(o.environmentVariables.DOTNET_MODIFIABLE_ASSEMBLIES=n);const r=e.headers.get("ASPNETCORE-BROWSER-TOOLS");return r&&(o.environmentVariables.__ASPNETCORE_BROWSER_TOOLS=r),o}"function"!=typeof importScripts||globalThis.onmessage||(globalThis.dotnetSidecar=!0);const Se="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node,De="function"==typeof importScripts,Oe=De&&"undefined"!=typeof dotnetSidecar,Ce=De&&!Oe,ke="object"==typeof window||De&&!Se,Ie=!ke&&!Se;let Ue={},Pe={},Me={},Le={},Ne={},$e=!1;const ze={},We={config:ze},Fe={mono:{},binding:{},internal:Ne,module:We,loaderHelpers:Pe,runtimeHelpers:Ue,diagnosticHelpers:Me,api:Le};function Be(e,t){if(e)return;const o="Assert failed: "+("function"==typeof t?t():t),n=new Error(o);_(o,n),Ue.nativeAbort(n)}function Ve(){return void 0!==Pe.exitCode}function qe(){return Ue.runtimeReady&&!Ve()}function He(){Ve()&&Be(!1,`.NET runtime already exited with ${Pe.exitCode} ${Pe.exitReason}. You can use runtime.runMain() which doesn't exit the runtime.`),Ue.runtimeReady||Be(!1,".NET runtime didn't start yet. Please call dotnet.create() first.")}function Je(){ke&&(globalThis.addEventListener("unhandledrejection",et),globalThis.addEventListener("error",tt))}let Ze,Qe;function Ge(e){Qe&&Qe(e),Xe(e,Pe.exitReason)}function Ke(e){Ze&&Ze(e||Pe.exitReason),Xe(1,e||Pe.exitReason)}function Xe(t,o){var n,r;const i=o&&"object"==typeof o;t=i&&"number"==typeof o.status?o.status:void 0===t?-1:t;const s=i&&"string"==typeof o.message?o.message:""+o;(o=i?o:Ue.ExitStatus?function(e,t){const o=new Ue.ExitStatus(e);return o.message=t,o.toString=()=>t,o}(t,s):new Error("Exit with code "+t+" "+s)).status=t,o.message||(o.message=s);const a=""+(o.stack||(new Error).stack);try{Object.defineProperty(o,"stack",{get:()=>a})}catch(e){}const l=!!o.silent;if(o.silent=!0,Ve())Pe.diagnosticTracing&&b("mono_exit called after exit");else{try{We.onAbort==Ke&&(We.onAbort=Ze),We.onExit==Ge&&(We.onExit=Qe),ke&&(globalThis.removeEventListener("unhandledrejection",et),globalThis.removeEventListener("error",tt)),Ue.runtimeReady?(Ue.jiterpreter_dump_stats&&Ue.jiterpreter_dump_stats(!1),0===t&&(null===(n=Pe.config)||void 0===n?void 0:n.interopCleanupOnExit)&&Ue.forceDisposeProxies(!0,!0),e&&0!==t&&(null===(r=Pe.config)||void 0===r||r.dumpThreadsOnNonZeroExit)):(Pe.diagnosticTracing&&b(`abort_startup, reason: ${o}`),function(e){Pe.allDownloadsQueued.promise_control.reject(e),Pe.allDownloadsFinished.promise_control.reject(e),Pe.afterConfigLoaded.promise_control.reject(e),Pe.wasmCompilePromise.promise_control.reject(e),Pe.runtimeModuleLoaded.promise_control.reject(e),Ue.dotnetReady&&(Ue.dotnetReady.promise_control.reject(e),Ue.afterInstantiateWasm.promise_control.reject(e),Ue.beforePreInit.promise_control.reject(e),Ue.afterPreInit.promise_control.reject(e),Ue.afterPreRun.promise_control.reject(e),Ue.beforeOnRuntimeInitialized.promise_control.reject(e),Ue.afterOnRuntimeInitialized.promise_control.reject(e),Ue.afterPostRun.promise_control.reject(e))}(o))}catch(e){E("mono_exit A failed",e)}try{l||(function(e,t){if(0!==e&&t){const e=Ue.ExitStatus&&t instanceof Ue.ExitStatus?b:_;"string"==typeof t?e(t):(void 0===t.stack&&(t.stack=(new Error).stack+""),t.message?e(Ue.stringify_as_error_with_stack?Ue.stringify_as_error_with_stack(t.message+"\n"+t.stack):t.message+"\n"+t.stack):e(JSON.stringify(t)))}!Ce&&Pe.config&&(Pe.config.logExitCode?Pe.config.forwardConsoleLogsToWS?R("WASM EXIT "+e):v("WASM EXIT "+e):Pe.config.forwardConsoleLogsToWS&&R())}(t,o),function(e){if(ke&&!Ce&&Pe.config&&Pe.config.appendElementOnExit&&document){const t=document.createElement("label");t.id="tests_done",0!==e&&(t.style.background="red"),t.innerHTML=""+e,document.body.appendChild(t)}}(t))}catch(e){E("mono_exit B failed",e)}Pe.exitCode=t,Pe.exitReason||(Pe.exitReason=o),!Ce&&Ue.runtimeReady&&We.runtimeKeepalivePop()}if(Pe.config&&Pe.config.asyncFlushOnExit&&0===t)throw(async()=>{try{await async function(){try{const e=await import(/*! webpackIgnore: true */"process"),t=e=>new Promise(((t,o)=>{e.on("error",o),e.end("","utf8",t)})),o=t(e.stderr),n=t(e.stdout);let r;const i=new Promise((e=>{r=setTimeout((()=>e("timeout")),1e3)}));await Promise.race([Promise.all([n,o]),i]),clearTimeout(r)}catch(e){_(`flushing std* streams failed: ${e}`)}}()}finally{Ye(t,o)}})(),o;Ye(t,o)}function Ye(e,t){if(Ue.runtimeReady&&Ue.nativeExit)try{Ue.nativeExit(e)}catch(e){!Ue.ExitStatus||e instanceof Ue.ExitStatus||E("set_exit_code_and_quit_now failed: "+e.toString())}if(0!==e||!ke)throw Se&&Ne.process?Ne.process.exit(e):Ue.quit&&Ue.quit(e,t),t}function et(e){ot(e,e.reason,"rejection")}function tt(e){ot(e,e.error,"error")}function ot(e,t,o){e.preventDefault();try{t||(t=new Error("Unhandled "+o)),void 0===t.stack&&(t.stack=(new Error).stack),t.stack=t.stack+"",t.silent||(_("Unhandled error:",t),Xe(1,t))}catch(e){}}!function(e){if($e)throw new Error("Loader module already loaded");$e=!0,Ue=e.runtimeHelpers,Pe=e.loaderHelpers,Me=e.diagnosticHelpers,Le=e.api,Ne=e.internal,Object.assign(Le,{INTERNAL:Ne,invokeLibraryInitializers:be}),Object.assign(e.module,{config:ve(ze,{environmentVariables:{}})});const r={mono_wasm_bindings_is_ready:!1,config:e.module.config,diagnosticTracing:!1,nativeAbort:e=>{throw e||new Error("abort")},nativeExit:e=>{throw new Error("exit:"+e)}},l={gitHash:"c2435c3e0f46de784341ac3ed62863ce77e117b4",config:e.module.config,diagnosticTracing:!1,maxParallelDownloads:16,enableDownloadRetry:!0,_loaded_files:[],loadedFiles:[],loadedAssemblies:[],libraryInitializers:[],workerNextNumber:1,actual_downloaded_assets_count:0,actual_instantiated_assets_count:0,expected_downloaded_assets_count:0,expected_instantiated_assets_count:0,afterConfigLoaded:i(),allDownloadsQueued:i(),allDownloadsFinished:i(),wasmCompilePromise:i(),runtimeModuleLoaded:i(),loadingWorkers:i(),is_exited:Ve,is_runtime_running:qe,assert_runtime_running:He,mono_exit:Xe,createPromiseController:i,getPromiseController:s,assertIsControllablePromise:a,mono_download_assets:oe,resolve_single_asset_path:ee,setup_proxy_console:j,set_thread_prefix:w,installUnhandledErrorHandler:Je,retrieve_asset_download:ie,invokeLibraryInitializers:be,isDebuggingSupported:Te,exceptions:t,simd:n,relaxedSimd:o};Object.assign(Ue,r),Object.assign(Pe,l)}(Fe);let nt,rt,it,st=!1,at=!1;async function lt(e){if(!at){if(at=!0,ke&&Pe.config.forwardConsoleLogsToWS&&void 0!==globalThis.WebSocket&&j("main",globalThis.console,globalThis.location.origin),We||Be(!1,"Null moduleConfig"),Pe.config||Be(!1,"Null moduleConfig.config"),"function"==typeof e){const t=e(Fe.api);if(t.ready)throw new Error("Module.ready couldn't be redefined.");Object.assign(We,t),Ee(We,t)}else{if("object"!=typeof e)throw new Error("Can't use moduleFactory callback of createDotnetRuntime function.");Ee(We,e)}await async function(e){if(Se){const e=await import(/*! webpackIgnore: true */"process"),t=14;if(e.versions.node.split(".")[0]<t)throw new Error(`NodeJS at '${e.execPath}' has too low version '${e.versions.node}', please use at least ${t}. See also https://aka.ms/dotnet-wasm-features`)}const t=/*! webpackIgnore: true */import.meta.url,o=t.indexOf("?");var n;if(o>0&&(Pe.modulesUniqueQuery=t.substring(o)),Pe.scriptUrl=t.replace(/\\/g,"/").replace(/[?#].*/,""),Pe.scriptDirectory=(n=Pe.scriptUrl).slice(0,n.lastIndexOf("/"))+"/",Pe.locateFile=e=>"URL"in globalThis&&globalThis.URL!==C?new URL(e,Pe.scriptDirectory).toString():M(e)?e:Pe.scriptDirectory+e,Pe.fetch_like=k,Pe.out=console.log,Pe.err=console.error,Pe.onDownloadResourceProgress=e.onDownloadResourceProgress,ke&&globalThis.navigator){const e=globalThis.navigator,t=e.userAgentData&&e.userAgentData.brands;t&&t.length>0?Pe.isChromium=t.some((e=>"Google Chrome"===e.brand||"Microsoft Edge"===e.brand||"Chromium"===e.brand)):e.userAgent&&(Pe.isChromium=e.userAgent.includes("Chrome"),Pe.isFirefox=e.userAgent.includes("Firefox"))}Ne.require=Se?await import(/*! webpackIgnore: true */"module").then((e=>e.createRequire(/*! webpackIgnore: true */import.meta.url))):Promise.resolve((()=>{throw new Error("require not supported")})),void 0===globalThis.URL&&(globalThis.URL=C)}(We)}}async function ct(e){return await lt(e),Ze=We.onAbort,Qe=We.onExit,We.onAbort=Ke,We.onExit=Ge,We.ENVIRONMENT_IS_PTHREAD?async function(){(function(){const e=new MessageChannel,t=e.port1,o=e.port2;t.addEventListener("message",(e=>{var n,r;n=JSON.parse(e.data.config),r=JSON.parse(e.data.monoThreadInfo),st?Pe.diagnosticTracing&&b("mono config already received"):(ve(Pe.config,n),Ue.monoThreadInfo=r,xe(),Pe.diagnosticTracing&&b("mono config received"),st=!0,Pe.afterConfigLoaded.promise_control.resolve(Pe.config),ke&&n.forwardConsoleLogsToWS&&void 0!==globalThis.WebSocket&&Pe.setup_proxy_console("worker-idle",console,globalThis.location.origin)),t.close(),o.close()}),{once:!0}),t.start(),self.postMessage({[l]:{monoCmd:"preload",port:o}},[o])})(),await Pe.afterConfigLoaded.promise,function(){const e=Pe.config;e.assets||Be(!1,"config.assets must be defined");for(const t of e.assets)X(t),Q[t.behavior]&&z.push(t)}(),setTimeout((async()=>{try{await oe()}catch(e){Xe(1,e)}}),0);const e=dt(),t=await Promise.all(e);return await ut(t),We}():async function(){var e;await Re(We),re();const t=dt();(async function(){try{const e=ee("dotnetwasm");await se(e),e&&e.pendingDownloadInternal&&e.pendingDownloadInternal.response||Be(!1,"Can't load dotnet.native.wasm");const t=await e.pendingDownloadInternal.response,o=t.headers&&t.headers.get?t.headers.get("Content-Type"):void 0;let n;if("function"==typeof WebAssembly.compileStreaming&&"application/wasm"===o)n=await WebAssembly.compileStreaming(t);else{ke&&"application/wasm"!==o&&E('WebAssembly resource does not have the expected content type "application/wasm", so falling back to slower ArrayBuffer instantiation.');const e=await t.arrayBuffer();Pe.diagnosticTracing&&b("instantiate_wasm_module buffered"),n=Ie?await Promise.resolve(new WebAssembly.Module(e)):await WebAssembly.compile(e)}e.pendingDownloadInternal=null,e.pendingDownload=null,e.buffer=null,e.moduleExports=null,Pe.wasmCompilePromise.promise_control.resolve(n)}catch(e){Pe.wasmCompilePromise.promise_control.reject(e)}})(),setTimeout((async()=>{try{D(),await oe()}catch(e){Xe(1,e)}}),0);const o=await Promise.all(t);return await ut(o),await Ue.dotnetReady.promise,await we(null===(e=Pe.config.resources)||void 0===e?void 0:e.modulesAfterRuntimeReady),await be("onRuntimeReady",[Fe.api]),Le}()}function dt(){const e=ee("js-module-runtime"),t=ee("js-module-native");if(nt&&rt)return[nt,rt,it];"object"==typeof e.moduleExports?nt=e.moduleExports:(Pe.diagnosticTracing&&b(`Attempting to import '${e.resolvedUrl}' for ${e.name}`),nt=import(/*! webpackIgnore: true */e.resolvedUrl)),"object"==typeof t.moduleExports?rt=t.moduleExports:(Pe.diagnosticTracing&&b(`Attempting to import '${t.resolvedUrl}' for ${t.name}`),rt=import(/*! webpackIgnore: true */t.resolvedUrl));const o=Y("js-module-diagnostics");return o&&("object"==typeof o.moduleExports?it=o.moduleExports:(Pe.diagnosticTracing&&b(`Attempting to import '${o.resolvedUrl}' for ${o.name}`),it=import(/*! webpackIgnore: true */o.resolvedUrl))),[nt,rt,it]}async function ut(e){const{initializeExports:t,initializeReplacements:o,configureRuntimeStartup:n,configureEmscriptenStartup:r,configureWorkerStartup:i,setRuntimeGlobals:s,passEmscriptenInternals:a}=e[0],{default:l}=e[1],c=e[2];s(Fe),t(Fe),c&&c.setRuntimeGlobals(Fe),await n(We),Pe.runtimeModuleLoaded.promise_control.resolve(),l((e=>(Object.assign(We,{ready:e.ready,__dotnet_runtime:{initializeReplacements:o,configureEmscriptenStartup:r,configureWorkerStartup:i,passEmscriptenInternals:a}}),We))).catch((e=>{if(e.message&&e.message.toLowerCase().includes("out of memory"))throw new Error(".NET runtime has failed to start, because too much memory was requested. Please decrease the memory by adjusting EmccMaximumHeapSize. See also https://aka.ms/dotnet-wasm-features");throw e}))}const ft=new class{withModuleConfig(e){try{return Ee(We,e),this}catch(e){throw Xe(1,e),e}}withOnConfigLoaded(e){try{return Ee(We,{onConfigLoaded:e}),this}catch(e){throw Xe(1,e),e}}withConsoleForwarding(){try{return ve(ze,{forwardConsoleLogsToWS:!0}),this}catch(e){throw Xe(1,e),e}}withExitOnUnhandledError(){try{return ve(ze,{exitOnUnhandledError:!0}),Je(),this}catch(e){throw Xe(1,e),e}}withAsyncFlushOnExit(){try{return ve(ze,{asyncFlushOnExit:!0}),this}catch(e){throw Xe(1,e),e}}withExitCodeLogging(){try{return ve(ze,{logExitCode:!0}),this}catch(e){throw Xe(1,e),e}}withElementOnExit(){try{return ve(ze,{appendElementOnExit:!0}),this}catch(e){throw Xe(1,e),e}}withInteropCleanupOnExit(){try{return ve(ze,{interopCleanupOnExit:!0}),this}catch(e){throw Xe(1,e),e}}withDumpThreadsOnNonZeroExit(){try{return ve(ze,{dumpThreadsOnNonZeroExit:!0}),this}catch(e){throw Xe(1,e),e}}withWaitingForDebugger(e){try{return ve(ze,{waitForDebugger:e}),this}catch(e){throw Xe(1,e),e}}withInterpreterPgo(e,t){try{return ve(ze,{interpreterPgo:e,interpreterPgoSaveDelay:t}),ze.runtimeOptions?ze.runtimeOptions.push("--interp-pgo-recording"):ze.runtimeOptions=["--interp-pgo-recording"],this}catch(e){throw Xe(1,e),e}}withConfig(e){try{return ve(ze,e),this}catch(e){throw Xe(1,e),e}}withConfigSrc(e){try{return e&&"string"==typeof e||Be(!1,"must be file path or URL"),Ee(We,{configSrc:e}),this}catch(e){throw Xe(1,e),e}}withVirtualWorkingDirectory(e){try{return e&&"string"==typeof e||Be(!1,"must be directory path"),ve(ze,{virtualWorkingDirectory:e}),this}catch(e){throw Xe(1,e),e}}withEnvironmentVariable(e,t){try{const o={};return o[e]=t,ve(ze,{environmentVariables:o}),this}catch(e){throw Xe(1,e),e}}withEnvironmentVariables(e){try{return e&&"object"==typeof e||Be(!1,"must be dictionary object"),ve(ze,{environmentVariables:e}),this}catch(e){throw Xe(1,e),e}}withDiagnosticTracing(e){try{return"boolean"!=typeof e&&Be(!1,"must be boolean"),ve(ze,{diagnosticTracing:e}),this}catch(e){throw Xe(1,e),e}}withDebugging(e){try{return null!=e&&"number"==typeof e||Be(!1,"must be number"),ve(ze,{debugLevel:e}),this}catch(e){throw Xe(1,e),e}}withApplicationArguments(...e){try{return e&&Array.isArray(e)||Be(!1,"must be array of strings"),ve(ze,{applicationArguments:e}),this}catch(e){throw Xe(1,e),e}}withRuntimeOptions(e){try{return e&&Array.isArray(e)||Be(!1,"must be array of strings"),ze.runtimeOptions?ze.runtimeOptions.push(...e):ze.runtimeOptions=e,this}catch(e){throw Xe(1,e),e}}withMainAssembly(e){try{return ve(ze,{mainAssemblyName:e}),this}catch(e){throw Xe(1,e),e}}withApplicationArgumentsFromQuery(){try{if(!globalThis.window)throw new Error("Missing window to the query parameters from");if(void 0===globalThis.URLSearchParams)throw new Error("URLSearchParams is supported");const e=new URLSearchParams(globalThis.window.location.search).getAll("arg");return this.withApplicationArguments(...e)}catch(e){throw Xe(1,e),e}}withApplicationEnvironment(e){try{return ve(ze,{applicationEnvironment:e}),this}catch(e){throw Xe(1,e),e}}withApplicationCulture(e){try{return ve(ze,{applicationCulture:e}),this}catch(e){throw Xe(1,e),e}}withResourceLoader(e){try{return Pe.loadBootResource=e,this}catch(e){throw Xe(1,e),e}}async download(){try{await async function(){lt(We),await Re(We),re(),D(),oe(),await Pe.allDownloadsFinished.promise}()}catch(e){throw Xe(1,e),e}}async create(){try{return this.instance||(this.instance=await async function(){return await ct(We),Fe.api}()),this.instance}catch(e){throw Xe(1,e),e}}async run(){try{return We.config||Be(!1,"Null moduleConfig.config"),this.instance||await this.create(),this.instance.runMainAndExit()}catch(e){throw Xe(1,e),e}}},mt=Xe,gt=ct;Ie||"function"==typeof globalThis.URL||Be(!1,"This browser/engine doesn't support URL API. Please use a modern version. See also https://aka.ms/dotnet-wasm-features"),"function"!=typeof globalThis.BigInt64Array&&Be(!1,"This browser/engine doesn't support BigInt64Array API. Please use a modern version. See also https://aka.ms/dotnet-wasm-features"),ft.withConfig(/*json-start*/{
5
5
  "mainAssemblyName": "Motely.SingleThread",
6
6
  "resources": {
7
- "hash": "sha256-lAhimDWdV0+brw99rHPX9oPrhlYE0/80U/OJ78P0A2I=",
7
+ "hash": "sha256-9aeX1Cg6/smbHreV0TwMyq25cd09eOAbeAVwBvBj8r0=",
8
8
  "jsModuleNative": [
9
9
  {
10
10
  "name": "dotnet.native.2rnmjvcnrv.js"
@@ -17,22 +17,22 @@ var e=!1;const t=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,
17
17
  ],
18
18
  "wasmNative": [
19
19
  {
20
- "name": "dotnet.native.px7soob3pq.wasm",
21
- "integrity": "sha256-Lf+rWVpku1tK0d52m1Jk5w58KAIbwDHOeO9hYN69Prs=",
20
+ "name": "dotnet.native.ws3tq8jgzv.wasm",
21
+ "integrity": "sha256-gJ16oIvZugLi3shVlLrawQP4/4sWGe7Ruv9sWVrhNC4=",
22
22
  "cache": "force-cache"
23
23
  }
24
24
  ],
25
25
  "coreAssembly": [
26
26
  {
27
27
  "virtualPath": "Motely.SingleThread.wasm",
28
- "name": "Motely.SingleThread.8ilcic7m8e.wasm",
29
- "integrity": "sha256-IBbHAWKJuA2NBjsj9Da28sEc421SmNvutrHc0p8kROo=",
28
+ "name": "Motely.SingleThread.qdb6metss2.wasm",
29
+ "integrity": "sha256-4uJaKJCCTnyKd+H3i1YhOP2lAjb32BQCs/sdlXqHgBw=",
30
30
  "cache": "force-cache"
31
31
  },
32
32
  {
33
33
  "virtualPath": "Motely.wasm",
34
- "name": "Motely.187ix5j7r4.wasm",
35
- "integrity": "sha256-Edo8N894C6g5MeHDNlFEHGCmdsm6s7Izlxt5CDcgIR4=",
34
+ "name": "Motely.80zooe1g1b.wasm",
35
+ "integrity": "sha256-OOftLIMBDvgJ4VYVj+o2+qp3qeiJ5jKMZLWmrKjEOuE=",
36
36
  "cache": "force-cache"
37
37
  },
38
38
  {
@@ -85,8 +85,8 @@ var e=!1;const t=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,
85
85
  },
86
86
  {
87
87
  "virtualPath": "System.Private.CoreLib.wasm",
88
- "name": "System.Private.CoreLib.e4xpgjmfzj.wasm",
89
- "integrity": "sha256-7s+WGWHVotxn3LQVnX08pyRA7gw4CsrbR2uylBkMR7k=",
88
+ "name": "System.Private.CoreLib.t6vylij0to.wasm",
89
+ "integrity": "sha256-m0CSUquSIz6bJ4999TdrddBrr27TSq8MxEcsCB+3WfY=",
90
90
  "cache": "force-cache"
91
91
  },
92
92
  {
@@ -97,8 +97,8 @@ var e=!1;const t=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,
97
97
  },
98
98
  {
99
99
  "virtualPath": "System.Runtime.InteropServices.JavaScript.wasm",
100
- "name": "System.Runtime.InteropServices.JavaScript.60uq0t1ywb.wasm",
101
- "integrity": "sha256-Zj4HEn4hinFe0+KGHQO2N2v9RQF7ubgGqv01XyA8z0c=",
100
+ "name": "System.Runtime.InteropServices.JavaScript.4jnkqxblyl.wasm",
101
+ "integrity": "sha256-4N1gfzXsia3a7KlReU2R0c4pYgq8r5No2FAe8EObx9E=",
102
102
  "cache": "force-cache"
103
103
  },
104
104
  {
Binary file
Binary file
package/index.cjs ADDED
@@ -0,0 +1,92 @@
1
+ const import_meta_url=require('url').pathToFileURL(__filename).href;
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var index_exports = {};
21
+ __export(index_exports, {
22
+ loadMotely: () => loadMotely
23
+ });
24
+ module.exports = __toCommonJS(index_exports);
25
+ var import_node_url = require("node:url");
26
+ var import_node_path = require("node:path");
27
+ var import_node_url2 = require("node:url");
28
+ function _dir() {
29
+ return (0, import_node_path.dirname)((0, import_node_url.fileURLToPath)(import_meta_url));
30
+ }
31
+ function buildApi(raw, cachedCapabilities) {
32
+ return {
33
+ async getCapabilities() {
34
+ return cachedCapabilities;
35
+ },
36
+ async analyzeSeed(seed, deck, stake) {
37
+ const json = await raw.AnalyzeSeedAsync(seed, deck, stake);
38
+ const result = JSON.parse(json);
39
+ if (result.error && !result.seed)
40
+ throw new Error(result.error);
41
+ return result;
42
+ },
43
+ async validateJaml(jaml) {
44
+ const json = await raw.ValidateJamlAsync(jaml);
45
+ return JSON.parse(json);
46
+ },
47
+ async startJamlSearch(jamlContent, options) {
48
+ const { onProgress, onResult, ...searchParams } = options ?? {};
49
+ const optionsJson = JSON.stringify({
50
+ threadCount: 1,
51
+ batchCharCount: 4,
52
+ ...searchParams
53
+ });
54
+ const results = [];
55
+ const progressCb = onProgress ? (json) => {
56
+ const p = JSON.parse(json);
57
+ onProgress(p.seedsSearched, p.matchingSeeds, p.elapsedMs, p.resultCount);
58
+ } : () => {
59
+ };
60
+ const resultCb = (seed, score) => {
61
+ results.push({ seed, score });
62
+ onResult?.(seed, score);
63
+ };
64
+ const response = JSON.parse(await raw.StartJamlSearch(jamlContent, optionsJson, progressCb, resultCb));
65
+ if (response.error)
66
+ throw new Error(response.error);
67
+ return results;
68
+ },
69
+ dispose() {
70
+ void raw.DisposeSearch();
71
+ }
72
+ };
73
+ }
74
+ async function loadMotely(options) {
75
+ const frameworkPath = options?.frameworkPath ?? (0, import_node_path.join)(_dir(), "_framework");
76
+ const dotnetJsPath = (0, import_node_path.join)(frameworkPath, "dotnet.js");
77
+ const dotnetUrl = (0, import_node_url2.pathToFileURL)(dotnetJsPath).href;
78
+ const mod = await import(dotnetUrl);
79
+ const dotnet = mod.dotnet;
80
+ const runtime = await dotnet.withDiagnosticTracing(false).create();
81
+ const config = runtime.getConfig();
82
+ const allExports = await runtime.getAssemblyExports(config.mainAssemblyName);
83
+ const raw = allExports.Motely.BrowserWasm.MotelyWasmExports;
84
+ runtime.runMain?.().catch((err) => console.error("[motely-node] runMain failed:", err));
85
+ const capabilitiesJson = await raw.GetCapabilitiesAsync();
86
+ const cachedCapabilities = JSON.parse(capabilitiesJson);
87
+ return buildApi(raw, cachedCapabilities);
88
+ }
89
+ // Annotate the CommonJS export names for ESM import in node:
90
+ 0 && (module.exports = {
91
+ loadMotely
92
+ });
package/index.d.ts CHANGED
@@ -38,17 +38,6 @@ export interface SearchResultInfo {
38
38
  seed: string;
39
39
  score: number;
40
40
  }
41
- export interface SearchProgressInfo {
42
- type: 'progress';
43
- seedsSearched: number;
44
- matchingSeeds: number;
45
- elapsedMs: number;
46
- resultCount: number;
47
- }
48
- export interface SearchCompleteInfo {
49
- type: 'done';
50
- searchId: string;
51
- }
52
41
  export interface ValidateResult {
53
42
  valid: boolean;
54
43
  error?: string | null;
@@ -67,12 +56,11 @@ export interface SearchOptions {
67
56
  endBatch?: number;
68
57
  specificSeed?: string;
69
58
  palindrome?: boolean;
59
+ /** Called every ~2 seconds by the .NET search engine with current progress. */
70
60
  onProgress?: (seedsSearched: number, matchingSeeds: number, elapsedMs: number, resultCount: number) => void;
61
+ /** Called each time a matching seed is found during search. */
71
62
  onResult?: (seed: string, score: number) => void;
72
63
  }
73
- export interface ErrorResult {
74
- error: string;
75
- }
76
64
  export interface MotelyNodeApi {
77
65
  /** Get runtime capabilities (SIMD, threads, etc.) */
78
66
  getCapabilities(): Promise<CapabilitiesInfo>;
@@ -81,22 +69,18 @@ export interface MotelyNodeApi {
81
69
  /** Validate a JAML filter string. */
82
70
  validateJaml(jamlContent: string): Promise<ValidateResult>;
83
71
  /**
84
- * Start a JAML search. Returns a Promise that resolves when search completes.
85
- * Progress is pushed to onProgress/onResult callbacks.
72
+ * Run a JAML search. Resolves with all matching seeds when search completes.
73
+ * onProgress is called ~every 2s with stats; onResult is called per match as found.
86
74
  */
87
- startJamlSearch(jamlContent: string, options?: SearchOptions): Promise<void>;
88
- /** Dispose and cleanup */
75
+ startJamlSearch(jamlContent: string, options?: SearchOptions): Promise<SearchResultInfo[]>;
76
+ /** Stop any running search and release resources. */
89
77
  dispose(): void;
90
78
  }
91
- declare global {
92
- var __motelyOnProgress: (totalSeedsSearched: number, matchingSeeds: number, elapsedMs: number, resultCount: number) => void;
93
- var __motelyOnResult: (seed: string, score: number) => void;
79
+ export interface LoadMotelyOptions {
80
+ /** Path to the folder containing dotnet.js (default: package _framework). */
81
+ frameworkPath?: string;
94
82
  }
95
83
  /**
96
- * Load the Motely WASM runtime for Node.js and return the API.
97
- * Uses the browser WASM build with Node.js runtime adapter.
98
- * Call once at app startup; the returned object is reusable.
84
+ * Load the Motely WASM engine for Node.js. Call once at startup; reuse the returned API.
99
85
  */
100
- export declare function loadMotely(options?: {
101
- frameworkPath?: string;
102
- }): Promise<MotelyNodeApi>;
86
+ export declare function loadMotely(options?: LoadMotelyOptions): Promise<MotelyNodeApi>;
package/index.js CHANGED
@@ -1,37 +1,13 @@
1
- // Motely Node.js Package Entry Point
2
- // Uses the browser WASM build with Node.js runtime adapter
1
+ // Motely Node.js Package WASM-based Balatro seed engine
2
+ // Wraps .NET WASM exports (Motely.SingleThread / Motely.BrowserWasm)
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import { dirname, join } from 'node:path';
5
5
  import { pathToFileURL } from 'node:url';
6
- /**
7
- * Load the Motely WASM runtime for Node.js and return the API.
8
- * Uses the browser WASM build with Node.js runtime adapter.
9
- * Call once at app startup; the returned object is reusable.
10
- */
11
- export async function loadMotely(options) {
12
- const __filename = fileURLToPath(import.meta.url);
13
- const __dirname = dirname(__filename);
14
- const defaultFrameworkPath = join(__dirname, '_framework');
15
- const frameworkPath = options?.frameworkPath || defaultFrameworkPath;
16
- const dotnetJsPath = join(frameworkPath, 'dotnet.js');
17
- // Install no-op callbacks before runtime boots
18
- globalThis.__motelyOnProgress = () => { };
19
- globalThis.__motelyOnResult = () => { };
20
- // Convert to file:// URL for dynamic import
21
- const dotnetUrl = pathToFileURL(dotnetJsPath).href;
22
- // Dynamic import of .NET WASM entry point
23
- const { dotnet } = await import(dotnetUrl);
24
- const runtime = await dotnet.create();
25
- const config = runtime.getConfig();
26
- const allExports = await runtime.getAssemblyExports(config.mainAssemblyName);
27
- const raw = allExports.Motely.BrowserWasm.MotelyWasmExports;
28
- runtime.runMain().catch(err => console.error('[motely-node] runMain failed:', err));
29
- const [versionJson, capabilitiesJson] = await Promise.all([
30
- raw.GetVersionAsync(),
31
- raw.GetCapabilitiesAsync(),
32
- ]);
33
- const cachedCapabilities = JSON.parse(capabilitiesJson);
34
- const api = {
6
+ function _dir() {
7
+ return dirname(fileURLToPath(import.meta.url));
8
+ }
9
+ function buildApi(raw, cachedCapabilities) {
10
+ return {
35
11
  async getCapabilities() {
36
12
  return cachedCapabilities;
37
13
  },
@@ -48,25 +24,47 @@ export async function loadMotely(options) {
48
24
  },
49
25
  async startJamlSearch(jamlContent, options) {
50
26
  const { onProgress, onResult, ...searchParams } = options ?? {};
51
- globalThis.__motelyOnProgress = onProgress ?? (() => { });
52
- globalThis.__motelyOnResult = onResult ?? (() => { });
53
- // Default threadCount=1 and batchCharCount=4 for Node.js single-threaded WASM
54
- const withDefaults = {
27
+ const optionsJson = JSON.stringify({
55
28
  threadCount: 1,
56
29
  batchCharCount: 4,
57
30
  ...searchParams,
31
+ });
32
+ const results = [];
33
+ const progressCb = onProgress
34
+ ? (json) => {
35
+ const p = JSON.parse(json);
36
+ onProgress(p.seedsSearched, p.matchingSeeds, p.elapsedMs, p.resultCount);
37
+ }
38
+ : () => { };
39
+ const resultCb = (seed, score) => {
40
+ results.push({ seed, score });
41
+ onResult?.(seed, score);
58
42
  };
59
- const optionsJson = JSON.stringify(withDefaults);
60
- const resultJson = await raw.StartJamlSearch(jamlContent, optionsJson);
61
- globalThis.__motelyOnProgress = () => { };
62
- globalThis.__motelyOnResult = () => { };
63
- const result = JSON.parse(resultJson);
64
- if (result.error)
65
- throw new Error(result.error);
43
+ const response = JSON.parse(await raw.StartJamlSearch(jamlContent, optionsJson, progressCb, resultCb));
44
+ if (response.error)
45
+ throw new Error(response.error);
46
+ return results;
66
47
  },
67
- dispose: () => {
68
- raw.DisposeSearch();
48
+ dispose() {
49
+ void raw.DisposeSearch();
69
50
  },
70
51
  };
71
- return api;
52
+ }
53
+ /**
54
+ * Load the Motely WASM engine for Node.js. Call once at startup; reuse the returned API.
55
+ */
56
+ export async function loadMotely(options) {
57
+ const frameworkPath = options?.frameworkPath ?? join(_dir(), '_framework');
58
+ const dotnetJsPath = join(frameworkPath, 'dotnet.js');
59
+ const dotnetUrl = pathToFileURL(dotnetJsPath).href;
60
+ const mod = await import(dotnetUrl);
61
+ const dotnet = mod.dotnet;
62
+ const runtime = await dotnet.withDiagnosticTracing(false).create();
63
+ const config = runtime.getConfig();
64
+ const allExports = (await runtime.getAssemblyExports(config.mainAssemblyName));
65
+ const raw = allExports.Motely.BrowserWasm.MotelyWasmExports;
66
+ runtime.runMain?.().catch((err) => console.error('[motely-node] runMain failed:', err));
67
+ const capabilitiesJson = await raw.GetCapabilitiesAsync();
68
+ const cachedCapabilities = JSON.parse(capabilitiesJson);
69
+ return buildApi(raw, cachedCapabilities);
72
70
  }
@@ -0,0 +1,510 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://seedfinder.app/jaml.schema.json",
4
+ "version": "2.2.3",
5
+ "title": "JAML - Jimbo's Ante Markup Language",
6
+ "description": "Schema for Balatro seed filter configuration files (.jaml)",
7
+ "type": "object",
8
+ "properties": {
9
+ "name": {
10
+ "type": "string",
11
+ "description": "Display name of the filter"
12
+ },
13
+ "description": {
14
+ "type": "string",
15
+ "description": "Description of what this filter searches for"
16
+ },
17
+ "author": {
18
+ "type": "string",
19
+ "description": "Creator of the filter"
20
+ },
21
+ "dateCreated": {
22
+ "type": "string",
23
+ "format": "date-time",
24
+ "description": "ISO 8601 timestamp when filter was created"
25
+ },
26
+ "deck": {
27
+ "type": "string",
28
+ "enum": [
29
+ "Red",
30
+ "Blue",
31
+ "Yellow",
32
+ "Green",
33
+ "Black",
34
+ "Magic",
35
+ "Nebula",
36
+ "Ghost",
37
+ "Abandoned",
38
+ "Checkered",
39
+ "Zodiac",
40
+ "Painted",
41
+ "Anaglyph",
42
+ "Plasma",
43
+ "Erratic",
44
+ "Challenge"
45
+ ],
46
+ "default": "Red",
47
+ "description": "Balatro deck to search with"
48
+ },
49
+ "stake": {
50
+ "type": "string",
51
+ "enum": [
52
+ "White",
53
+ "Red",
54
+ "Green",
55
+ "Black",
56
+ "Blue",
57
+ "Purple",
58
+ "Orange",
59
+ "Gold"
60
+ ],
61
+ "default": "White",
62
+ "description": "Balatro stake level"
63
+ },
64
+ "defaults": {
65
+ "type": "object",
66
+ "description": "Default values applied to clauses when not specified",
67
+ "properties": {
68
+ "antes": {
69
+ "type": "array",
70
+ "items": {
71
+ "type": "integer",
72
+ "minimum": 0,
73
+ "maximum": 39
74
+ },
75
+ "default": [
76
+ 1,
77
+ 2,
78
+ 3,
79
+ 4,
80
+ 5,
81
+ 6,
82
+ 7,
83
+ 8
84
+ ],
85
+ "description": "Default antes to check if not specified in clause"
86
+ },
87
+ "boosterPacks": {
88
+ "type": "array",
89
+ "items": {
90
+ "type": "integer",
91
+ "minimum": 0,
92
+ "maximum": 5
93
+ },
94
+ "default": [
95
+ 0,
96
+ 1,
97
+ 2,
98
+ 3,
99
+ 4,
100
+ 5
101
+ ],
102
+ "description": "Default pack slots (ante 1 limited to 0-3, ante 2+ uses 0-5)"
103
+ },
104
+ "shopItems": {
105
+ "type": "array",
106
+ "items": {
107
+ "type": "integer",
108
+ "minimum": 0,
109
+ "maximum": 5
110
+ },
111
+ "default": [
112
+ 0,
113
+ 1,
114
+ 2,
115
+ 3,
116
+ 4,
117
+ 5
118
+ ],
119
+ "description": "Default shop slots (ante 1 limited to 0-3, ante 2+ uses 0-5)"
120
+ },
121
+ "score": {
122
+ "type": "integer",
123
+ "minimum": 0,
124
+ "default": 1,
125
+ "description": "Default score for 'should' clauses"
126
+ }
127
+ },
128
+ "additionalProperties": false
129
+ },
130
+ "must": {
131
+ "type": "array",
132
+ "description": "Items that MUST appear in the seed (required)",
133
+ "items": {
134
+ "$ref": "#/definitions/clause"
135
+ }
136
+ },
137
+ "should": {
138
+ "type": "array",
139
+ "description": "Items that SHOULD appear for bonus scoring (optional)",
140
+ "items": {
141
+ "$ref": "#/definitions/clause"
142
+ }
143
+ },
144
+ "mustNot": {
145
+ "type": "array",
146
+ "description": "Items that MUST NOT appear in the seed (banned)",
147
+ "items": {
148
+ "$ref": "#/definitions/clause"
149
+ }
150
+ }
151
+ },
152
+ "definitions": {
153
+ "clause": {
154
+ "type": "object",
155
+ "properties": {
156
+ "type": {
157
+ "type": "string",
158
+ "enum": [
159
+ "Joker",
160
+ "SoulJoker",
161
+ "Voucher",
162
+ "TarotCard",
163
+ "Planet",
164
+ "PlanetCard",
165
+ "Spectral",
166
+ "SpectralCard",
167
+ "Tag",
168
+ "SmallBlindTag",
169
+ "BigBlindTag",
170
+ "Boss",
171
+ "BossBlind",
172
+ "StandardCard",
173
+ "Event",
174
+ "ErraticRank",
175
+ "ErraticSuit",
176
+ "And",
177
+ "Or"
178
+ ],
179
+ "description": "Type of item to search for"
180
+ },
181
+ "value": {
182
+ "type": "string",
183
+ "description": "Name of the specific item (e.g., 'Perkeo', 'Hieroglyph'). For Event type, this is the event type name (e.g., 'LuckyMoney', 'LuckyMult'). Shorthand: use 'event: LuckyMoney' instead of 'type: Event, value: LuckyMoney'"
184
+ },
185
+ "eventType": {
186
+ "type": "string",
187
+ "enum": [
188
+ "LuckyMoney",
189
+ "LuckyMult",
190
+ "MisprintMult",
191
+ "WheelOfFortune",
192
+ "CavendishExtinct",
193
+ "GrosMichelExtinct"
194
+ ],
195
+ "description": "Event type (alternative to 'value' for Event clauses). Shorthand: use 'event: LuckyMoney' instead."
196
+ },
197
+ "rolls": {
198
+ "type": "array",
199
+ "items": {
200
+ "type": "integer",
201
+ "minimum": 0
202
+ },
203
+ "description": "Roll indices for Event clauses (e.g. [0, 1] for first two occurrences of the event). Only valid for type: Event. Example: 'rolls: [0]' checks the first occurrence"
204
+ },
205
+ "event": {
206
+ "type": "string",
207
+ "description": "Shorthand for Event type (type-as-key). Example: 'event: LuckyMoney'"
208
+ },
209
+ "joker": {
210
+ "type": "string",
211
+ "description": "Shorthand for Joker type. Example: 'joker: Blueprint'"
212
+ },
213
+ "legendaryJoker": {
214
+ "type": "string",
215
+ "description": "Shorthand for SoulJoker type. Example: 'legendaryJoker: Perkeo'"
216
+ },
217
+ "voucher": {
218
+ "type": "string",
219
+ "description": "Shorthand for Voucher type."
220
+ },
221
+ "tarot": {
222
+ "type": "string",
223
+ "description": "Shorthand for TarotCard type."
224
+ },
225
+ "tarotCard": {
226
+ "type": "string",
227
+ "description": "Shorthand for TarotCard type."
228
+ },
229
+ "planet": {
230
+ "type": "string",
231
+ "description": "Shorthand for PlanetCard type."
232
+ },
233
+ "planetCard": {
234
+ "type": "string",
235
+ "description": "Shorthand for PlanetCard type."
236
+ },
237
+ "spectral": {
238
+ "type": "string",
239
+ "description": "Shorthand for SpectralCard type."
240
+ },
241
+ "spectralCard": {
242
+ "type": "string",
243
+ "description": "Shorthand for SpectralCard type."
244
+ },
245
+ "standardCard": {
246
+ "type": "string",
247
+ "description": "Shorthand for StandardCard type."
248
+ },
249
+ "boss": {
250
+ "type": "string",
251
+ "description": "Shorthand for Boss type."
252
+ },
253
+ "tag": {
254
+ "type": "string",
255
+ "description": "Shorthand for Tag type."
256
+ },
257
+ "smallBlindTag": {
258
+ "type": "string",
259
+ "description": "Shorthand for SmallBlindTag type."
260
+ },
261
+ "bigBlindTag": {
262
+ "type": "string",
263
+ "description": "Shorthand for BigBlindTag type."
264
+ },
265
+ "erraticRank": {
266
+ "type": "string",
267
+ "description": "Shorthand for ErraticRank type."
268
+ },
269
+ "erraticSuit": {
270
+ "type": "string",
271
+ "description": "Shorthand for ErraticSuit type."
272
+ },
273
+ "erraticCard": {
274
+ "type": "string",
275
+ "description": "Shorthand for ErraticCard type."
276
+ },
277
+ "antes": {
278
+ "type": "array",
279
+ "items": {
280
+ "type": "integer",
281
+ "minimum": 0,
282
+ "maximum": 39
283
+ },
284
+ "description": "Which antes (0-39) to search in"
285
+ },
286
+ "score": {
287
+ "type": "integer",
288
+ "minimum": 0,
289
+ "default": 1,
290
+ "description": "Scoring weight for 'should' clauses"
291
+ },
292
+ "label": {
293
+ "type": "string",
294
+ "description": "Custom label for display in results"
295
+ },
296
+ "edition": {
297
+ "type": "string",
298
+ "enum": [
299
+ "Foil",
300
+ "Holographic",
301
+ "Polychrome",
302
+ "Negative"
303
+ ],
304
+ "description": "Required edition for the item"
305
+ },
306
+ "seal": {
307
+ "type": "string",
308
+ "enum": [
309
+ "Red",
310
+ "Blue",
311
+ "Gold",
312
+ "Purple"
313
+ ],
314
+ "description": "Required seal for playing cards"
315
+ },
316
+ "enhancement": {
317
+ "type": "string",
318
+ "enum": [
319
+ "Bonus",
320
+ "Mult",
321
+ "Wild",
322
+ "Glass",
323
+ "Steel",
324
+ "Stone",
325
+ "Lucky",
326
+ "Gold"
327
+ ],
328
+ "description": "Required enhancement for playing cards"
329
+ },
330
+ "rank": {
331
+ "type": "string",
332
+ "enum": [
333
+ "2",
334
+ "3",
335
+ "4",
336
+ "5",
337
+ "6",
338
+ "7",
339
+ "8",
340
+ "9",
341
+ "10",
342
+ "J",
343
+ "Jack",
344
+ "Q",
345
+ "Queen",
346
+ "K",
347
+ "King",
348
+ "A",
349
+ "Ace"
350
+ ],
351
+ "description": "Card rank for playing cards (abbreviation or full name)"
352
+ },
353
+ "suit": {
354
+ "type": "string",
355
+ "enum": [
356
+ "Hearts",
357
+ "Diamonds",
358
+ "Clubs",
359
+ "Spades"
360
+ ],
361
+ "description": "Card suit for playing cards"
362
+ },
363
+ "sources": {
364
+ "type": "object",
365
+ "properties": {
366
+ "shopItems": {
367
+ "type": "array",
368
+ "items": {
369
+ "type": "integer"
370
+ },
371
+ "description": "Shop slot indices (0-based). If empty array [], will be populated from minshopItem/maxshopItem if provided."
372
+ },
373
+ "boosterPacks": {
374
+ "type": "array",
375
+ "items": {
376
+ "type": "integer"
377
+ },
378
+ "description": "Pack slot indices (0-based). If empty array [], will be populated from minboosterPack/maxboosterPack if provided."
379
+ },
380
+ "minshopItem": {
381
+ "type": "integer",
382
+ "minimum": 0,
383
+ "maximum": 1023,
384
+ "description": "Minimum shop slot index (inclusive). If specified with maxshopItem, generates shopItems array [minshopItem..maxshopItem]."
385
+ },
386
+ "maxshopItem": {
387
+ "type": "integer",
388
+ "minimum": 0,
389
+ "maximum": 1023,
390
+ "description": "Maximum shop slot index (inclusive). If specified with minshopItem, generates shopItems array [minshopItem..maxshopItem]."
391
+ },
392
+ "minboosterPack": {
393
+ "type": "integer",
394
+ "minimum": 0,
395
+ "maximum": 5,
396
+ "description": "Minimum pack slot index (inclusive). If specified with maxboosterPack, generates boosterPacks array [minboosterPack..maxboosterPack]."
397
+ },
398
+ "maxboosterPack": {
399
+ "type": "integer",
400
+ "minimum": 0,
401
+ "maximum": 5,
402
+ "description": "Maximum pack slot index (inclusive). If specified with minboosterPack, generates boosterPacks array [minboosterPack..maxboosterPack]."
403
+ },
404
+ "tags": {
405
+ "type": "boolean",
406
+ "description": "Whether item can come from tags (Rare Tag, Uncommon Tag, Negative Tag)"
407
+ },
408
+ "requireMega": {
409
+ "type": "boolean",
410
+ "description": "Whether pack must be a Mega pack (for pack slots 4-5)"
411
+ },
412
+ "judgement": {
413
+ "type": "array",
414
+ "items": {
415
+ "type": "integer"
416
+ },
417
+ "description": "Judgement tarot joker roll indices (e.g. [0, 1] for first two uses)"
418
+ },
419
+ "rareTag": {
420
+ "type": "array",
421
+ "items": {
422
+ "type": "integer"
423
+ },
424
+ "description": "Rare tag joker roll indices (e.g. [0] for first rare tag)"
425
+ },
426
+ "uncommonTag": {
427
+ "type": "array",
428
+ "items": {
429
+ "type": "integer"
430
+ },
431
+ "description": "Uncommon tag joker roll indices (e.g. [0] for first uncommon tag)"
432
+ },
433
+ "riffRaff": {
434
+ "type": "array",
435
+ "items": {
436
+ "type": "integer"
437
+ },
438
+ "description": "RiffRaff joker roll indices (e.g. [0, 1] for first two RiffRaff jokers - RiffRaff creates 2 jokers)"
439
+ },
440
+ "purpleSealOrEightBall": {
441
+ "type": "array",
442
+ "items": {
443
+ "type": "integer"
444
+ },
445
+ "description": "Purple Seal / 8Ball tarot card roll indices (e.g. [0] for first tarot from Purple Seal or 8Ball - both use same PRNG key)"
446
+ },
447
+ "emperor": {
448
+ "type": "array",
449
+ "items": {
450
+ "type": "integer"
451
+ },
452
+ "description": "Emperor tarot card roll indices (e.g. [0, 1] for first two tarot cards from Emperor - Emperor creates 2 tarot cards)"
453
+ },
454
+ "sixthSense": {
455
+ "type": "array",
456
+ "items": {
457
+ "type": "integer"
458
+ },
459
+ "description": "SixthSense spectral card roll indices (e.g. [0] for first spectral card from SixthSense joker)"
460
+ },
461
+ "seance": {
462
+ "type": "array",
463
+ "items": {
464
+ "type": "integer"
465
+ },
466
+ "description": "Seance spectral card roll indices (e.g. [0, 1] for first two spectral cards from Seance joker)"
467
+ },
468
+ "uncommonShopJokers": {
469
+ "type": "array",
470
+ "items": {
471
+ "type": "integer"
472
+ },
473
+ "description": "Raw uncommon shop joker stream roll indices - FAST pre-filter that bypasses shop item type check (e.g. [0, 1, 2] for first 3 uncommon jokers in stream)"
474
+ },
475
+ "rareShopJokers": {
476
+ "type": "array",
477
+ "items": {
478
+ "type": "integer"
479
+ },
480
+ "description": "Raw rare shop joker stream roll indices - FAST pre-filter that bypasses shop item type check (e.g. [0] for first rare joker in stream)"
481
+ },
482
+ "commonShopJokers": {
483
+ "type": "array",
484
+ "items": {
485
+ "type": "integer"
486
+ },
487
+ "description": "Raw common shop joker stream roll indices - FAST pre-filter that bypasses shop item type check (e.g. [0, 1] for first 2 common jokers in stream)"
488
+ }
489
+ },
490
+ "additionalProperties": false,
491
+ "description": "Where the item can be found - object with source-specific roll indices. If sources: is specified (even with empty arrays), the Sources object will exist after processing."
492
+ },
493
+ "and": {
494
+ "type": "array",
495
+ "items": {
496
+ "$ref": "#/definitions/clause"
497
+ },
498
+ "description": "Nested AND conditions"
499
+ },
500
+ "or": {
501
+ "type": "array",
502
+ "items": {
503
+ "$ref": "#/definitions/clause"
504
+ },
505
+ "description": "Nested OR conditions (any match)"
506
+ }
507
+ }
508
+ }
509
+ }
510
+ }
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "motely-node",
3
- "version": "2.2.0",
3
+ "version": "2.2.3",
4
4
  "description": "MotelyJAML for Node.js/V8 - Balatro seed analyzer and JAML filter engine using .NET WASM",
5
5
  "type": "module",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
+ "types": "./index.d.ts",
10
11
  "import": "./index.js",
11
- "require": "./index.cjs",
12
- "types": "./index.d.ts"
12
+ "require": "./index.cjs"
13
13
  },
14
14
  "./jaml.schema.json": "./jaml.schema.json"
15
15
  },
@@ -41,17 +41,21 @@
41
41
  },
42
42
  "license": "MIT",
43
43
  "engines": {
44
- "node": ">=18.0.0"
44
+ "node": ">=24.0.0"
45
45
  },
46
46
  "dependencies": {},
47
+ "optionalDependencies": {
48
+ "node-api-dotnet": "^0.9.0"
49
+ },
47
50
  "devDependencies": {
48
51
  "typescript": "^5.0.0",
49
- "@types/node": "^20.0.0"
52
+ "@types/node": "^24.0.0",
53
+ "esbuild": "^0.24.0"
50
54
  },
51
55
  "scripts": {
52
- "build": "tsc",
56
+ "build": "tsc && esbuild index.js --outfile=index.cjs --format=cjs --platform=node --banner:js=\"const import_meta_url=require('url').pathToFileURL(__filename).href;\" --define:import.meta.url=import_meta_url",
53
57
  "copy-framework": "node copy-framework.js",
54
- "prepare": "npm run build && npm run copy-framework",
55
- "prepublishOnly": "npm run build"
58
+ "prepublishOnly": "npm run build",
59
+ "prove": "node prove-node.mjs && node -e \"console.log(require('fs').readFileSync('prove-node-result.txt','utf8'))\""
56
60
  }
57
61
  }
Binary file
Binary file