@mcmcjs/stan-wasm 0.0.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/LICENSE +21 -0
- package/README.md +70 -0
- package/dist/chunk-3CMLUNUW.js +206 -0
- package/dist/chunk-3CMLUNUW.js.map +1 -0
- package/dist/index.cjs +229 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.cjs +377 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +17 -0
- package/dist/react/index.d.ts +17 -0
- package/dist/react/index.js +163 -0
- package/dist/react/index.js.map +1 -0
- package/dist/sampler-4wflmHRA.d.cts +76 -0
- package/dist/sampler-4wflmHRA.d.ts +76 -0
- package/dist/worker.js +360 -0
- package/dist/worker.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/react/index.ts
|
|
21
|
+
var react_exports = {};
|
|
22
|
+
__export(react_exports, {
|
|
23
|
+
StanWasmSamplerProvider: () => StanWasmSamplerProvider,
|
|
24
|
+
useStanWasmSampler: () => useStanWasmSampler,
|
|
25
|
+
useStanWasmSamplerContext: () => useStanWasmSamplerContext
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(react_exports);
|
|
28
|
+
|
|
29
|
+
// src/react/StanWasmSamplerProvider.tsx
|
|
30
|
+
var import_react2 = require("react");
|
|
31
|
+
|
|
32
|
+
// src/react/useStanWasmSampler.ts
|
|
33
|
+
var import_react = require("react");
|
|
34
|
+
|
|
35
|
+
// src/compile-client.ts
|
|
36
|
+
var trimTrailingSlash = (url) => url.replace(/\/+$/, "");
|
|
37
|
+
async function compileStanCode(req) {
|
|
38
|
+
const base = trimTrailingSlash(req.serverUrl);
|
|
39
|
+
const headers = { "Content-Type": "text/plain" };
|
|
40
|
+
if (req.passcode) {
|
|
41
|
+
headers.Authorization = `Bearer ${req.passcode}`;
|
|
42
|
+
}
|
|
43
|
+
const res = await fetch(`${base}/compile`, {
|
|
44
|
+
method: "POST",
|
|
45
|
+
headers,
|
|
46
|
+
body: req.stanCode,
|
|
47
|
+
signal: req.signal
|
|
48
|
+
});
|
|
49
|
+
if (!res.ok) {
|
|
50
|
+
const text = await res.text().catch(() => "");
|
|
51
|
+
throw new Error(`Stan WASM compile failed (HTTP ${res.status}): ${text || res.statusText}`);
|
|
52
|
+
}
|
|
53
|
+
const json = await res.json();
|
|
54
|
+
if (typeof json.model_id !== "string" || json.model_id.length === 0) {
|
|
55
|
+
throw new Error("Stan WASM compile response did not include a model_id");
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
modelId: json.model_id,
|
|
59
|
+
mainJsUrl: `${base}/download/${json.model_id}/main.js`
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/sampler.ts
|
|
64
|
+
var import_meta = {};
|
|
65
|
+
var defaultWorkerUrl = () => {
|
|
66
|
+
try {
|
|
67
|
+
return new URL("./worker.js", import_meta.url);
|
|
68
|
+
} catch {
|
|
69
|
+
throw new Error(
|
|
70
|
+
'@mcmcjs/stan-wasm could not resolve its worker URL automatically. Pass `workerUrl` explicitly to the StanSampler constructor (e.g. import workerUrl from "@mcmcjs/stan-wasm/worker?url" in Vite).'
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
var calculateRefreshRate = (cfg) => {
|
|
75
|
+
const total = (cfg.num_warmup + cfg.num_samples) * cfg.num_chains;
|
|
76
|
+
const twoHalfPercent = Math.floor(total / 40);
|
|
77
|
+
const nearestTen = Math.round(twoHalfPercent / 10) * 10;
|
|
78
|
+
return Math.max(15, nearestTen);
|
|
79
|
+
};
|
|
80
|
+
var StanSampler = class {
|
|
81
|
+
#compileServerUrl;
|
|
82
|
+
#passcode;
|
|
83
|
+
#workerUrl;
|
|
84
|
+
#worker = null;
|
|
85
|
+
#lastCompile = null;
|
|
86
|
+
#samplingStartTimeSec = 0;
|
|
87
|
+
#loadResolve = null;
|
|
88
|
+
#loadReject = null;
|
|
89
|
+
#sampleResolve = null;
|
|
90
|
+
#sampleReject = null;
|
|
91
|
+
#activeListener = null;
|
|
92
|
+
constructor(opts) {
|
|
93
|
+
this.#compileServerUrl = opts.compileServerUrl;
|
|
94
|
+
this.#passcode = opts.passcode;
|
|
95
|
+
this.#workerUrl = opts.workerUrl ?? defaultWorkerUrl();
|
|
96
|
+
}
|
|
97
|
+
get isReady() {
|
|
98
|
+
return this.#worker !== null && this.#lastCompile !== null;
|
|
99
|
+
}
|
|
100
|
+
get lastCompile() {
|
|
101
|
+
return this.#lastCompile;
|
|
102
|
+
}
|
|
103
|
+
async compile(stanCode, signal) {
|
|
104
|
+
this.#teardown(new Error("Superseded by a new compile()"));
|
|
105
|
+
const result = await compileStanCode({
|
|
106
|
+
serverUrl: this.#compileServerUrl,
|
|
107
|
+
passcode: this.#passcode,
|
|
108
|
+
stanCode,
|
|
109
|
+
signal
|
|
110
|
+
});
|
|
111
|
+
await this.#startWorker(result.mainJsUrl);
|
|
112
|
+
this.#lastCompile = result;
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
sample(config, listener) {
|
|
116
|
+
if (!this.#worker) {
|
|
117
|
+
return Promise.reject(
|
|
118
|
+
new Error("No model loaded \u2014 call compile() and await it before sample()")
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
if (this.#sampleResolve !== null) {
|
|
122
|
+
return Promise.reject(new Error("A sampling run is already in progress on this sampler"));
|
|
123
|
+
}
|
|
124
|
+
return new Promise((resolve, reject) => {
|
|
125
|
+
this.#sampleResolve = resolve;
|
|
126
|
+
this.#sampleReject = reject;
|
|
127
|
+
this.#activeListener = listener ?? null;
|
|
128
|
+
this.#samplingStartTimeSec = performance.now() / 1e3;
|
|
129
|
+
const fullConfig = {
|
|
130
|
+
...config,
|
|
131
|
+
seed: config.seed ?? Math.floor(Math.random() * 2 ** 32),
|
|
132
|
+
refresh: config.refresh ?? calculateRefreshRate(config)
|
|
133
|
+
};
|
|
134
|
+
this.#worker?.postMessage({ kind: "sample" /* Sample */, sampleConfig: fullConfig });
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
cancel() {
|
|
138
|
+
this.#teardown(new Error("Cancelled"));
|
|
139
|
+
}
|
|
140
|
+
#teardown(rejectionReason) {
|
|
141
|
+
if (this.#worker) {
|
|
142
|
+
this.#worker.terminate();
|
|
143
|
+
this.#worker = null;
|
|
144
|
+
}
|
|
145
|
+
this.#loadReject?.(rejectionReason);
|
|
146
|
+
this.#sampleReject?.(rejectionReason);
|
|
147
|
+
this.#loadResolve = null;
|
|
148
|
+
this.#loadReject = null;
|
|
149
|
+
this.#sampleResolve = null;
|
|
150
|
+
this.#sampleReject = null;
|
|
151
|
+
this.#activeListener = null;
|
|
152
|
+
this.#lastCompile = null;
|
|
153
|
+
}
|
|
154
|
+
#startWorker(url) {
|
|
155
|
+
const worker = new Worker(this.#workerUrl, { type: "module" });
|
|
156
|
+
this.#worker = worker;
|
|
157
|
+
worker.onmessage = (event) => {
|
|
158
|
+
this.#onWorkerMessage(event.data);
|
|
159
|
+
};
|
|
160
|
+
worker.onerror = (event) => {
|
|
161
|
+
const message = event.message || "Worker error";
|
|
162
|
+
const err = new Error(`Stan WASM worker error: ${message}`);
|
|
163
|
+
if (this.#loadReject) {
|
|
164
|
+
this.#loadReject(err);
|
|
165
|
+
this.#loadResolve = null;
|
|
166
|
+
this.#loadReject = null;
|
|
167
|
+
} else if (this.#sampleReject) {
|
|
168
|
+
this.#sampleReject(err);
|
|
169
|
+
this.#sampleResolve = null;
|
|
170
|
+
this.#sampleReject = null;
|
|
171
|
+
this.#activeListener = null;
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
return new Promise((resolve, reject) => {
|
|
175
|
+
this.#loadResolve = resolve;
|
|
176
|
+
this.#loadReject = reject;
|
|
177
|
+
worker.postMessage({ kind: "load" /* Load */, url });
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
#onWorkerMessage(msg) {
|
|
181
|
+
switch (msg.kind) {
|
|
182
|
+
case "modelLoaded" /* ModelLoaded */: {
|
|
183
|
+
const resolve = this.#loadResolve;
|
|
184
|
+
this.#loadResolve = null;
|
|
185
|
+
this.#loadReject = null;
|
|
186
|
+
resolve?.();
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
case "modelLoadError" /* ModelLoadError */: {
|
|
190
|
+
const reject = this.#loadReject;
|
|
191
|
+
this.#loadResolve = null;
|
|
192
|
+
this.#loadReject = null;
|
|
193
|
+
reject?.(new Error(`Stan WASM model load failed: ${msg.error}`));
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
case "progress" /* Progress */: {
|
|
197
|
+
this.#activeListener?.({ type: "progress", report: msg.report });
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
case "stanReturn" /* StanReturn */: {
|
|
201
|
+
const resolve = this.#sampleResolve;
|
|
202
|
+
const reject = this.#sampleReject;
|
|
203
|
+
const listener = this.#activeListener;
|
|
204
|
+
this.#sampleResolve = null;
|
|
205
|
+
this.#sampleReject = null;
|
|
206
|
+
this.#activeListener = null;
|
|
207
|
+
if (msg.error !== null) {
|
|
208
|
+
listener?.({ type: "error", error: msg.error });
|
|
209
|
+
reject?.(new Error(`Stan sampling failed: ${msg.error}`));
|
|
210
|
+
} else {
|
|
211
|
+
const run = {
|
|
212
|
+
draws: msg.draws,
|
|
213
|
+
paramNames: msg.paramNames,
|
|
214
|
+
computeTimeSec: performance.now() / 1e3 - this.#samplingStartTimeSec,
|
|
215
|
+
consoleMessages: msg.consoleMessages,
|
|
216
|
+
sampleConfig: msg.sampleConfig
|
|
217
|
+
};
|
|
218
|
+
listener?.({ type: "done", run });
|
|
219
|
+
resolve?.(run);
|
|
220
|
+
}
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
// src/react/useStanWasmSampler.ts
|
|
228
|
+
var import_meta2 = {};
|
|
229
|
+
var REACT_FALLBACK_WORKER_URL = (() => {
|
|
230
|
+
try {
|
|
231
|
+
return new URL("../worker.js", import_meta2.url).href;
|
|
232
|
+
} catch {
|
|
233
|
+
return void 0;
|
|
234
|
+
}
|
|
235
|
+
})();
|
|
236
|
+
var initialState = {
|
|
237
|
+
compileStatus: "idle",
|
|
238
|
+
sampleStatus: "idle",
|
|
239
|
+
compileError: null,
|
|
240
|
+
sampleError: null,
|
|
241
|
+
progress: null,
|
|
242
|
+
latestRun: null,
|
|
243
|
+
consoleMessages: [],
|
|
244
|
+
modelId: null,
|
|
245
|
+
mainJsUrl: null
|
|
246
|
+
};
|
|
247
|
+
var reducer = (state, action) => {
|
|
248
|
+
switch (action.type) {
|
|
249
|
+
case "compile:start":
|
|
250
|
+
return {
|
|
251
|
+
...state,
|
|
252
|
+
compileStatus: "compiling",
|
|
253
|
+
compileError: null,
|
|
254
|
+
sampleStatus: "idle",
|
|
255
|
+
sampleError: null,
|
|
256
|
+
progress: null,
|
|
257
|
+
modelId: null,
|
|
258
|
+
mainJsUrl: null
|
|
259
|
+
};
|
|
260
|
+
case "compile:done":
|
|
261
|
+
return {
|
|
262
|
+
...state,
|
|
263
|
+
compileStatus: "ready",
|
|
264
|
+
modelId: action.modelId,
|
|
265
|
+
mainJsUrl: action.mainJsUrl
|
|
266
|
+
};
|
|
267
|
+
case "compile:error":
|
|
268
|
+
return {
|
|
269
|
+
...state,
|
|
270
|
+
compileStatus: "error",
|
|
271
|
+
compileError: action.error
|
|
272
|
+
};
|
|
273
|
+
case "sample:start":
|
|
274
|
+
return {
|
|
275
|
+
...state,
|
|
276
|
+
sampleStatus: "sampling",
|
|
277
|
+
sampleError: null,
|
|
278
|
+
progress: null,
|
|
279
|
+
latestRun: null,
|
|
280
|
+
consoleMessages: []
|
|
281
|
+
};
|
|
282
|
+
case "sample:progress":
|
|
283
|
+
return { ...state, progress: action.progress };
|
|
284
|
+
case "sample:done":
|
|
285
|
+
return {
|
|
286
|
+
...state,
|
|
287
|
+
sampleStatus: "done",
|
|
288
|
+
latestRun: action.run,
|
|
289
|
+
consoleMessages: action.run.consoleMessages
|
|
290
|
+
};
|
|
291
|
+
case "sample:error":
|
|
292
|
+
return { ...state, sampleStatus: "error", sampleError: action.error };
|
|
293
|
+
case "reset":
|
|
294
|
+
return initialState;
|
|
295
|
+
default:
|
|
296
|
+
return state;
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
function useStanWasmSampler(opts) {
|
|
300
|
+
const [state, dispatch] = (0, import_react.useReducer)(reducer, initialState);
|
|
301
|
+
const samplerRef = (0, import_react.useRef)(null);
|
|
302
|
+
const { compileServerUrl, passcode } = opts;
|
|
303
|
+
const workerUrl = opts.workerUrl ?? REACT_FALLBACK_WORKER_URL;
|
|
304
|
+
(0, import_react.useEffect)(() => {
|
|
305
|
+
const sampler = new StanSampler({ compileServerUrl, passcode, workerUrl });
|
|
306
|
+
samplerRef.current = sampler;
|
|
307
|
+
return () => {
|
|
308
|
+
sampler.cancel();
|
|
309
|
+
if (samplerRef.current === sampler) {
|
|
310
|
+
samplerRef.current = null;
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
}, [compileServerUrl, passcode, workerUrl]);
|
|
314
|
+
const compile = (0, import_react.useCallback)(async (stanCode) => {
|
|
315
|
+
const sampler = samplerRef.current;
|
|
316
|
+
if (!sampler) throw new Error("Sampler not yet initialised");
|
|
317
|
+
dispatch({ type: "compile:start" });
|
|
318
|
+
try {
|
|
319
|
+
const result = await sampler.compile(stanCode);
|
|
320
|
+
dispatch({
|
|
321
|
+
type: "compile:done",
|
|
322
|
+
modelId: result.modelId,
|
|
323
|
+
mainJsUrl: result.mainJsUrl
|
|
324
|
+
});
|
|
325
|
+
} catch (err) {
|
|
326
|
+
dispatch({
|
|
327
|
+
type: "compile:error",
|
|
328
|
+
error: err instanceof Error ? err.message : String(err)
|
|
329
|
+
});
|
|
330
|
+
throw err;
|
|
331
|
+
}
|
|
332
|
+
}, []);
|
|
333
|
+
const sample = (0, import_react.useCallback)(async (config, listener) => {
|
|
334
|
+
const sampler = samplerRef.current;
|
|
335
|
+
if (!sampler) throw new Error("Sampler not yet initialised");
|
|
336
|
+
dispatch({ type: "sample:start" });
|
|
337
|
+
const wrappedListener = (event) => {
|
|
338
|
+
if (event.type === "progress") {
|
|
339
|
+
dispatch({ type: "sample:progress", progress: event.report });
|
|
340
|
+
}
|
|
341
|
+
listener?.(event);
|
|
342
|
+
};
|
|
343
|
+
try {
|
|
344
|
+
const run = await sampler.sample(config, wrappedListener);
|
|
345
|
+
dispatch({ type: "sample:done", run });
|
|
346
|
+
return run;
|
|
347
|
+
} catch (err) {
|
|
348
|
+
dispatch({
|
|
349
|
+
type: "sample:error",
|
|
350
|
+
error: err instanceof Error ? err.message : String(err)
|
|
351
|
+
});
|
|
352
|
+
throw err;
|
|
353
|
+
}
|
|
354
|
+
}, []);
|
|
355
|
+
const cancel = (0, import_react.useCallback)(() => {
|
|
356
|
+
samplerRef.current?.cancel();
|
|
357
|
+
dispatch({ type: "reset" });
|
|
358
|
+
}, []);
|
|
359
|
+
return { state, compile, sample, cancel };
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// src/react/StanWasmSamplerProvider.tsx
|
|
363
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
364
|
+
var StanWasmSamplerContext = (0, import_react2.createContext)(null);
|
|
365
|
+
function StanWasmSamplerProvider(props) {
|
|
366
|
+
const { children, ...opts } = props;
|
|
367
|
+
const sampler = useStanWasmSampler(opts);
|
|
368
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StanWasmSamplerContext.Provider, { value: sampler, children });
|
|
369
|
+
}
|
|
370
|
+
function useStanWasmSamplerContext() {
|
|
371
|
+
const value = (0, import_react2.useContext)(StanWasmSamplerContext);
|
|
372
|
+
if (!value) {
|
|
373
|
+
throw new Error("useStanWasmSamplerContext must be called inside a <StanWasmSamplerProvider>");
|
|
374
|
+
}
|
|
375
|
+
return value;
|
|
376
|
+
}
|
|
377
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/index.ts","../../src/react/StanWasmSamplerProvider.tsx","../../src/react/useStanWasmSampler.ts","../../src/compile-client.ts","../../src/sampler.ts"],"sourcesContent":["export {\n StanWasmSamplerProvider,\n type StanWasmSamplerProviderProps,\n useStanWasmSamplerContext,\n} from \"./StanWasmSamplerProvider\";\nexport {\n type UseStanWasmSamplerReturn,\n useStanWasmSampler,\n} from \"./useStanWasmSampler\";\n","import { createContext, type PropsWithChildren, useContext } from \"react\";\nimport type { StanSamplerOptions } from \"../sampler\";\nimport { type UseStanWasmSamplerReturn, useStanWasmSampler } from \"./useStanWasmSampler\";\n\nconst StanWasmSamplerContext = createContext<UseStanWasmSamplerReturn | null>(null);\n\nexport type StanWasmSamplerProviderProps = PropsWithChildren<StanSamplerOptions>;\n\nexport function StanWasmSamplerProvider(props: StanWasmSamplerProviderProps) {\n const { children, ...opts } = props;\n const sampler = useStanWasmSampler(opts);\n return (\n <StanWasmSamplerContext.Provider value={sampler}>{children}</StanWasmSamplerContext.Provider>\n );\n}\n\nexport function useStanWasmSamplerContext(): UseStanWasmSamplerReturn {\n const value = useContext(StanWasmSamplerContext);\n if (!value) {\n throw new Error(\"useStanWasmSamplerContext must be called inside a <StanWasmSamplerProvider>\");\n }\n return value;\n}\n","import { useCallback, useEffect, useReducer, useRef } from \"react\";\nimport { StanSampler, type StanSamplerOptions } from \"../sampler\";\n\nconst REACT_FALLBACK_WORKER_URL = (() => {\n try {\n return new URL(\"../worker.js\", import.meta.url).href;\n } catch {\n return undefined;\n }\n})();\n\nimport type {\n ConsoleMessage,\n Progress,\n SampleConfig,\n SamplerEvent,\n SamplerListener,\n SamplerState,\n StanRun,\n} from \"../types\";\n\ntype Action =\n | { type: \"compile:start\" }\n | { type: \"compile:done\"; modelId: string; mainJsUrl: string }\n | { type: \"compile:error\"; error: string }\n | { type: \"sample:start\" }\n | { type: \"sample:progress\"; progress: Progress }\n | { type: \"sample:done\"; run: StanRun }\n | { type: \"sample:error\"; error: string }\n | { type: \"reset\" };\n\nconst initialState: SamplerState = {\n compileStatus: \"idle\",\n sampleStatus: \"idle\",\n compileError: null,\n sampleError: null,\n progress: null,\n latestRun: null,\n consoleMessages: [],\n modelId: null,\n mainJsUrl: null,\n};\n\nconst reducer = (state: SamplerState, action: Action): SamplerState => {\n switch (action.type) {\n case \"compile:start\":\n return {\n ...state,\n compileStatus: \"compiling\",\n compileError: null,\n sampleStatus: \"idle\",\n sampleError: null,\n progress: null,\n modelId: null,\n mainJsUrl: null,\n };\n case \"compile:done\":\n return {\n ...state,\n compileStatus: \"ready\",\n modelId: action.modelId,\n mainJsUrl: action.mainJsUrl,\n };\n case \"compile:error\":\n return {\n ...state,\n compileStatus: \"error\",\n compileError: action.error,\n };\n case \"sample:start\":\n return {\n ...state,\n sampleStatus: \"sampling\",\n sampleError: null,\n progress: null,\n latestRun: null,\n consoleMessages: [],\n };\n case \"sample:progress\":\n return { ...state, progress: action.progress };\n case \"sample:done\":\n return {\n ...state,\n sampleStatus: \"done\",\n latestRun: action.run,\n consoleMessages: action.run.consoleMessages,\n };\n case \"sample:error\":\n return { ...state, sampleStatus: \"error\", sampleError: action.error };\n case \"reset\":\n return initialState;\n default:\n return state;\n }\n};\n\nexport interface UseStanWasmSamplerReturn {\n state: SamplerState;\n compile: (stanCode: string) => Promise<void>;\n sample: (config: SampleConfig, listener?: SamplerListener) => Promise<StanRun>;\n cancel: () => void;\n}\n\nexport function useStanWasmSampler(opts: StanSamplerOptions): UseStanWasmSamplerReturn {\n const [state, dispatch] = useReducer(reducer, initialState);\n const samplerRef = useRef<StanSampler | null>(null);\n const { compileServerUrl, passcode } = opts;\n const workerUrl = opts.workerUrl ?? REACT_FALLBACK_WORKER_URL;\n\n useEffect(() => {\n const sampler = new StanSampler({ compileServerUrl, passcode, workerUrl });\n samplerRef.current = sampler;\n return () => {\n sampler.cancel();\n if (samplerRef.current === sampler) {\n samplerRef.current = null;\n }\n };\n }, [compileServerUrl, passcode, workerUrl]);\n\n const compile = useCallback(async (stanCode: string) => {\n const sampler = samplerRef.current;\n if (!sampler) throw new Error(\"Sampler not yet initialised\");\n dispatch({ type: \"compile:start\" });\n try {\n const result = await sampler.compile(stanCode);\n dispatch({\n type: \"compile:done\",\n modelId: result.modelId,\n mainJsUrl: result.mainJsUrl,\n });\n } catch (err) {\n dispatch({\n type: \"compile:error\",\n error: err instanceof Error ? err.message : String(err),\n });\n throw err;\n }\n }, []);\n\n const sample = useCallback(async (config: SampleConfig, listener?: SamplerListener) => {\n const sampler = samplerRef.current;\n if (!sampler) throw new Error(\"Sampler not yet initialised\");\n dispatch({ type: \"sample:start\" });\n const wrappedListener: SamplerListener = (event: SamplerEvent) => {\n if (event.type === \"progress\") {\n dispatch({ type: \"sample:progress\", progress: event.report });\n }\n listener?.(event);\n };\n try {\n const run = await sampler.sample(config, wrappedListener);\n dispatch({ type: \"sample:done\", run });\n return run;\n } catch (err) {\n dispatch({\n type: \"sample:error\",\n error: err instanceof Error ? err.message : String(err),\n });\n throw err;\n }\n }, []);\n\n const cancel = useCallback(() => {\n samplerRef.current?.cancel();\n dispatch({ type: \"reset\" });\n }, []);\n\n return { state, compile, sample, cancel };\n}\n\nexport type { ConsoleMessage, SamplerState };\n","import type { CompileResult } from \"./types\";\n\nexport interface CompileRequest {\n serverUrl: string;\n passcode?: string;\n stanCode: string;\n signal?: AbortSignal;\n}\n\nconst trimTrailingSlash = (url: string): string => url.replace(/\\/+$/, \"\");\n\nexport async function compileStanCode(req: CompileRequest): Promise<CompileResult> {\n const base = trimTrailingSlash(req.serverUrl);\n const headers: Record<string, string> = { \"Content-Type\": \"text/plain\" };\n if (req.passcode) {\n headers.Authorization = `Bearer ${req.passcode}`;\n }\n const res = await fetch(`${base}/compile`, {\n method: \"POST\",\n headers,\n body: req.stanCode,\n signal: req.signal,\n });\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Stan WASM compile failed (HTTP ${res.status}): ${text || res.statusText}`);\n }\n const json = (await res.json()) as { model_id?: unknown };\n if (typeof json.model_id !== \"string\" || json.model_id.length === 0) {\n throw new Error(\"Stan WASM compile response did not include a model_id\");\n }\n return {\n modelId: json.model_id,\n mainJsUrl: `${base}/download/${json.model_id}/main.js`,\n };\n}\n\nexport async function probeServer(opts: { serverUrl: string }): Promise<boolean> {\n const base = trimTrailingSlash(opts.serverUrl);\n try {\n const res = await fetch(`${base}/probe`, { method: \"POST\" });\n return res.ok;\n } catch {\n return false;\n }\n}\n","import { compileStanCode } from \"./compile-client\";\nimport {\n type CompileResult,\n type SampleConfig,\n type SamplerListener,\n type StanRun,\n WorkerReply,\n type WorkerReplyMessage,\n WorkerRequest,\n} from \"./types\";\n\nexport interface StanSamplerOptions {\n compileServerUrl: string;\n passcode?: string;\n workerUrl?: string | URL;\n}\n\nconst defaultWorkerUrl = (): URL => {\n try {\n return new URL(\"./worker.js\", import.meta.url);\n } catch {\n throw new Error(\n '@mcmcjs/stan-wasm could not resolve its worker URL automatically. Pass `workerUrl` explicitly to the StanSampler constructor (e.g. import workerUrl from \"@mcmcjs/stan-wasm/worker?url\" in Vite).',\n );\n }\n};\n\nconst calculateRefreshRate = (cfg: SampleConfig): number => {\n const total = (cfg.num_warmup + cfg.num_samples) * cfg.num_chains;\n const twoHalfPercent = Math.floor(total / 40);\n const nearestTen = Math.round(twoHalfPercent / 10) * 10;\n return Math.max(15, nearestTen);\n};\n\nexport class StanSampler {\n readonly #compileServerUrl: string;\n readonly #passcode: string | undefined;\n readonly #workerUrl: string | URL;\n\n #worker: Worker | null = null;\n #lastCompile: CompileResult | null = null;\n #samplingStartTimeSec: number = 0;\n\n #loadResolve: (() => void) | null = null;\n #loadReject: ((err: Error) => void) | null = null;\n #sampleResolve: ((run: StanRun) => void) | null = null;\n #sampleReject: ((err: Error) => void) | null = null;\n #activeListener: SamplerListener | null = null;\n\n constructor(opts: StanSamplerOptions) {\n this.#compileServerUrl = opts.compileServerUrl;\n this.#passcode = opts.passcode;\n this.#workerUrl = opts.workerUrl ?? defaultWorkerUrl();\n }\n\n get isReady(): boolean {\n return this.#worker !== null && this.#lastCompile !== null;\n }\n\n get lastCompile(): CompileResult | null {\n return this.#lastCompile;\n }\n\n async compile(stanCode: string, signal?: AbortSignal): Promise<CompileResult> {\n this.#teardown(new Error(\"Superseded by a new compile()\"));\n const result = await compileStanCode({\n serverUrl: this.#compileServerUrl,\n passcode: this.#passcode,\n stanCode,\n signal,\n });\n await this.#startWorker(result.mainJsUrl);\n this.#lastCompile = result;\n return result;\n }\n\n sample(config: SampleConfig, listener?: SamplerListener): Promise<StanRun> {\n if (!this.#worker) {\n return Promise.reject(\n new Error(\"No model loaded — call compile() and await it before sample()\"),\n );\n }\n if (this.#sampleResolve !== null) {\n return Promise.reject(new Error(\"A sampling run is already in progress on this sampler\"));\n }\n return new Promise<StanRun>((resolve, reject) => {\n this.#sampleResolve = resolve;\n this.#sampleReject = reject;\n this.#activeListener = listener ?? null;\n this.#samplingStartTimeSec = performance.now() / 1000;\n const fullConfig: SampleConfig = {\n ...config,\n seed: config.seed ?? Math.floor(Math.random() * 2 ** 32),\n refresh: config.refresh ?? calculateRefreshRate(config),\n };\n this.#worker?.postMessage({ kind: WorkerRequest.Sample, sampleConfig: fullConfig });\n });\n }\n\n cancel(): void {\n this.#teardown(new Error(\"Cancelled\"));\n }\n\n #teardown(rejectionReason: Error): void {\n if (this.#worker) {\n this.#worker.terminate();\n this.#worker = null;\n }\n this.#loadReject?.(rejectionReason);\n this.#sampleReject?.(rejectionReason);\n this.#loadResolve = null;\n this.#loadReject = null;\n this.#sampleResolve = null;\n this.#sampleReject = null;\n this.#activeListener = null;\n this.#lastCompile = null;\n }\n\n #startWorker(url: string): Promise<void> {\n const worker = new Worker(this.#workerUrl, { type: \"module\" });\n this.#worker = worker;\n worker.onmessage = (event: MessageEvent<WorkerReplyMessage>) => {\n this.#onWorkerMessage(event.data);\n };\n worker.onerror = (event: ErrorEvent) => {\n const message = event.message || \"Worker error\";\n const err = new Error(`Stan WASM worker error: ${message}`);\n if (this.#loadReject) {\n this.#loadReject(err);\n this.#loadResolve = null;\n this.#loadReject = null;\n } else if (this.#sampleReject) {\n this.#sampleReject(err);\n this.#sampleResolve = null;\n this.#sampleReject = null;\n this.#activeListener = null;\n }\n };\n return new Promise<void>((resolve, reject) => {\n this.#loadResolve = resolve;\n this.#loadReject = reject;\n worker.postMessage({ kind: WorkerRequest.Load, url });\n });\n }\n\n #onWorkerMessage(msg: WorkerReplyMessage): void {\n switch (msg.kind) {\n case WorkerReply.ModelLoaded: {\n const resolve = this.#loadResolve;\n this.#loadResolve = null;\n this.#loadReject = null;\n resolve?.();\n break;\n }\n case WorkerReply.ModelLoadError: {\n const reject = this.#loadReject;\n this.#loadResolve = null;\n this.#loadReject = null;\n reject?.(new Error(`Stan WASM model load failed: ${msg.error}`));\n break;\n }\n case WorkerReply.Progress: {\n this.#activeListener?.({ type: \"progress\", report: msg.report });\n break;\n }\n case WorkerReply.StanReturn: {\n const resolve = this.#sampleResolve;\n const reject = this.#sampleReject;\n const listener = this.#activeListener;\n this.#sampleResolve = null;\n this.#sampleReject = null;\n this.#activeListener = null;\n if (msg.error !== null) {\n listener?.({ type: \"error\", error: msg.error });\n reject?.(new Error(`Stan sampling failed: ${msg.error}`));\n } else {\n const run: StanRun = {\n draws: msg.draws,\n paramNames: msg.paramNames,\n computeTimeSec: performance.now() / 1000 - this.#samplingStartTimeSec,\n consoleMessages: msg.consoleMessages,\n sampleConfig: msg.sampleConfig,\n };\n listener?.({ type: \"done\", run });\n resolve?.(run);\n }\n break;\n }\n }\n }\n}\n"],"mappings":"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","names":["import_react","import_meta"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { PropsWithChildren } from 'react';
|
|
3
|
+
import { f as SamplerState, S as SampleConfig, e as SamplerListener, h as StanRun, j as StanSamplerOptions } from '../sampler-4wflmHRA.cjs';
|
|
4
|
+
|
|
5
|
+
interface UseStanWasmSamplerReturn {
|
|
6
|
+
state: SamplerState;
|
|
7
|
+
compile: (stanCode: string) => Promise<void>;
|
|
8
|
+
sample: (config: SampleConfig, listener?: SamplerListener) => Promise<StanRun>;
|
|
9
|
+
cancel: () => void;
|
|
10
|
+
}
|
|
11
|
+
declare function useStanWasmSampler(opts: StanSamplerOptions): UseStanWasmSamplerReturn;
|
|
12
|
+
|
|
13
|
+
type StanWasmSamplerProviderProps = PropsWithChildren<StanSamplerOptions>;
|
|
14
|
+
declare function StanWasmSamplerProvider(props: StanWasmSamplerProviderProps): react.JSX.Element;
|
|
15
|
+
declare function useStanWasmSamplerContext(): UseStanWasmSamplerReturn;
|
|
16
|
+
|
|
17
|
+
export { StanWasmSamplerProvider, type StanWasmSamplerProviderProps, type UseStanWasmSamplerReturn, useStanWasmSampler, useStanWasmSamplerContext };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { PropsWithChildren } from 'react';
|
|
3
|
+
import { f as SamplerState, S as SampleConfig, e as SamplerListener, h as StanRun, j as StanSamplerOptions } from '../sampler-4wflmHRA.js';
|
|
4
|
+
|
|
5
|
+
interface UseStanWasmSamplerReturn {
|
|
6
|
+
state: SamplerState;
|
|
7
|
+
compile: (stanCode: string) => Promise<void>;
|
|
8
|
+
sample: (config: SampleConfig, listener?: SamplerListener) => Promise<StanRun>;
|
|
9
|
+
cancel: () => void;
|
|
10
|
+
}
|
|
11
|
+
declare function useStanWasmSampler(opts: StanSamplerOptions): UseStanWasmSamplerReturn;
|
|
12
|
+
|
|
13
|
+
type StanWasmSamplerProviderProps = PropsWithChildren<StanSamplerOptions>;
|
|
14
|
+
declare function StanWasmSamplerProvider(props: StanWasmSamplerProviderProps): react.JSX.Element;
|
|
15
|
+
declare function useStanWasmSamplerContext(): UseStanWasmSamplerReturn;
|
|
16
|
+
|
|
17
|
+
export { StanWasmSamplerProvider, type StanWasmSamplerProviderProps, type UseStanWasmSamplerReturn, useStanWasmSampler, useStanWasmSamplerContext };
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import {
|
|
2
|
+
StanSampler
|
|
3
|
+
} from "../chunk-3CMLUNUW.js";
|
|
4
|
+
|
|
5
|
+
// src/react/StanWasmSamplerProvider.tsx
|
|
6
|
+
import { createContext, useContext } from "react";
|
|
7
|
+
|
|
8
|
+
// src/react/useStanWasmSampler.ts
|
|
9
|
+
import { useCallback, useEffect, useReducer, useRef } from "react";
|
|
10
|
+
var REACT_FALLBACK_WORKER_URL = (() => {
|
|
11
|
+
try {
|
|
12
|
+
return new URL("../worker.js", import.meta.url).href;
|
|
13
|
+
} catch {
|
|
14
|
+
return void 0;
|
|
15
|
+
}
|
|
16
|
+
})();
|
|
17
|
+
var initialState = {
|
|
18
|
+
compileStatus: "idle",
|
|
19
|
+
sampleStatus: "idle",
|
|
20
|
+
compileError: null,
|
|
21
|
+
sampleError: null,
|
|
22
|
+
progress: null,
|
|
23
|
+
latestRun: null,
|
|
24
|
+
consoleMessages: [],
|
|
25
|
+
modelId: null,
|
|
26
|
+
mainJsUrl: null
|
|
27
|
+
};
|
|
28
|
+
var reducer = (state, action) => {
|
|
29
|
+
switch (action.type) {
|
|
30
|
+
case "compile:start":
|
|
31
|
+
return {
|
|
32
|
+
...state,
|
|
33
|
+
compileStatus: "compiling",
|
|
34
|
+
compileError: null,
|
|
35
|
+
sampleStatus: "idle",
|
|
36
|
+
sampleError: null,
|
|
37
|
+
progress: null,
|
|
38
|
+
modelId: null,
|
|
39
|
+
mainJsUrl: null
|
|
40
|
+
};
|
|
41
|
+
case "compile:done":
|
|
42
|
+
return {
|
|
43
|
+
...state,
|
|
44
|
+
compileStatus: "ready",
|
|
45
|
+
modelId: action.modelId,
|
|
46
|
+
mainJsUrl: action.mainJsUrl
|
|
47
|
+
};
|
|
48
|
+
case "compile:error":
|
|
49
|
+
return {
|
|
50
|
+
...state,
|
|
51
|
+
compileStatus: "error",
|
|
52
|
+
compileError: action.error
|
|
53
|
+
};
|
|
54
|
+
case "sample:start":
|
|
55
|
+
return {
|
|
56
|
+
...state,
|
|
57
|
+
sampleStatus: "sampling",
|
|
58
|
+
sampleError: null,
|
|
59
|
+
progress: null,
|
|
60
|
+
latestRun: null,
|
|
61
|
+
consoleMessages: []
|
|
62
|
+
};
|
|
63
|
+
case "sample:progress":
|
|
64
|
+
return { ...state, progress: action.progress };
|
|
65
|
+
case "sample:done":
|
|
66
|
+
return {
|
|
67
|
+
...state,
|
|
68
|
+
sampleStatus: "done",
|
|
69
|
+
latestRun: action.run,
|
|
70
|
+
consoleMessages: action.run.consoleMessages
|
|
71
|
+
};
|
|
72
|
+
case "sample:error":
|
|
73
|
+
return { ...state, sampleStatus: "error", sampleError: action.error };
|
|
74
|
+
case "reset":
|
|
75
|
+
return initialState;
|
|
76
|
+
default:
|
|
77
|
+
return state;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
function useStanWasmSampler(opts) {
|
|
81
|
+
const [state, dispatch] = useReducer(reducer, initialState);
|
|
82
|
+
const samplerRef = useRef(null);
|
|
83
|
+
const { compileServerUrl, passcode } = opts;
|
|
84
|
+
const workerUrl = opts.workerUrl ?? REACT_FALLBACK_WORKER_URL;
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
const sampler = new StanSampler({ compileServerUrl, passcode, workerUrl });
|
|
87
|
+
samplerRef.current = sampler;
|
|
88
|
+
return () => {
|
|
89
|
+
sampler.cancel();
|
|
90
|
+
if (samplerRef.current === sampler) {
|
|
91
|
+
samplerRef.current = null;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}, [compileServerUrl, passcode, workerUrl]);
|
|
95
|
+
const compile = useCallback(async (stanCode) => {
|
|
96
|
+
const sampler = samplerRef.current;
|
|
97
|
+
if (!sampler) throw new Error("Sampler not yet initialised");
|
|
98
|
+
dispatch({ type: "compile:start" });
|
|
99
|
+
try {
|
|
100
|
+
const result = await sampler.compile(stanCode);
|
|
101
|
+
dispatch({
|
|
102
|
+
type: "compile:done",
|
|
103
|
+
modelId: result.modelId,
|
|
104
|
+
mainJsUrl: result.mainJsUrl
|
|
105
|
+
});
|
|
106
|
+
} catch (err) {
|
|
107
|
+
dispatch({
|
|
108
|
+
type: "compile:error",
|
|
109
|
+
error: err instanceof Error ? err.message : String(err)
|
|
110
|
+
});
|
|
111
|
+
throw err;
|
|
112
|
+
}
|
|
113
|
+
}, []);
|
|
114
|
+
const sample = useCallback(async (config, listener) => {
|
|
115
|
+
const sampler = samplerRef.current;
|
|
116
|
+
if (!sampler) throw new Error("Sampler not yet initialised");
|
|
117
|
+
dispatch({ type: "sample:start" });
|
|
118
|
+
const wrappedListener = (event) => {
|
|
119
|
+
if (event.type === "progress") {
|
|
120
|
+
dispatch({ type: "sample:progress", progress: event.report });
|
|
121
|
+
}
|
|
122
|
+
listener?.(event);
|
|
123
|
+
};
|
|
124
|
+
try {
|
|
125
|
+
const run = await sampler.sample(config, wrappedListener);
|
|
126
|
+
dispatch({ type: "sample:done", run });
|
|
127
|
+
return run;
|
|
128
|
+
} catch (err) {
|
|
129
|
+
dispatch({
|
|
130
|
+
type: "sample:error",
|
|
131
|
+
error: err instanceof Error ? err.message : String(err)
|
|
132
|
+
});
|
|
133
|
+
throw err;
|
|
134
|
+
}
|
|
135
|
+
}, []);
|
|
136
|
+
const cancel = useCallback(() => {
|
|
137
|
+
samplerRef.current?.cancel();
|
|
138
|
+
dispatch({ type: "reset" });
|
|
139
|
+
}, []);
|
|
140
|
+
return { state, compile, sample, cancel };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/react/StanWasmSamplerProvider.tsx
|
|
144
|
+
import { jsx } from "react/jsx-runtime";
|
|
145
|
+
var StanWasmSamplerContext = createContext(null);
|
|
146
|
+
function StanWasmSamplerProvider(props) {
|
|
147
|
+
const { children, ...opts } = props;
|
|
148
|
+
const sampler = useStanWasmSampler(opts);
|
|
149
|
+
return /* @__PURE__ */ jsx(StanWasmSamplerContext.Provider, { value: sampler, children });
|
|
150
|
+
}
|
|
151
|
+
function useStanWasmSamplerContext() {
|
|
152
|
+
const value = useContext(StanWasmSamplerContext);
|
|
153
|
+
if (!value) {
|
|
154
|
+
throw new Error("useStanWasmSamplerContext must be called inside a <StanWasmSamplerProvider>");
|
|
155
|
+
}
|
|
156
|
+
return value;
|
|
157
|
+
}
|
|
158
|
+
export {
|
|
159
|
+
StanWasmSamplerProvider,
|
|
160
|
+
useStanWasmSampler,
|
|
161
|
+
useStanWasmSamplerContext
|
|
162
|
+
};
|
|
163
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/StanWasmSamplerProvider.tsx","../../src/react/useStanWasmSampler.ts"],"sourcesContent":["import { createContext, type PropsWithChildren, useContext } from \"react\";\nimport type { StanSamplerOptions } from \"../sampler\";\nimport { type UseStanWasmSamplerReturn, useStanWasmSampler } from \"./useStanWasmSampler\";\n\nconst StanWasmSamplerContext = createContext<UseStanWasmSamplerReturn | null>(null);\n\nexport type StanWasmSamplerProviderProps = PropsWithChildren<StanSamplerOptions>;\n\nexport function StanWasmSamplerProvider(props: StanWasmSamplerProviderProps) {\n const { children, ...opts } = props;\n const sampler = useStanWasmSampler(opts);\n return (\n <StanWasmSamplerContext.Provider value={sampler}>{children}</StanWasmSamplerContext.Provider>\n );\n}\n\nexport function useStanWasmSamplerContext(): UseStanWasmSamplerReturn {\n const value = useContext(StanWasmSamplerContext);\n if (!value) {\n throw new Error(\"useStanWasmSamplerContext must be called inside a <StanWasmSamplerProvider>\");\n }\n return value;\n}\n","import { useCallback, useEffect, useReducer, useRef } from \"react\";\nimport { StanSampler, type StanSamplerOptions } from \"../sampler\";\n\nconst REACT_FALLBACK_WORKER_URL = (() => {\n try {\n return new URL(\"../worker.js\", import.meta.url).href;\n } catch {\n return undefined;\n }\n})();\n\nimport type {\n ConsoleMessage,\n Progress,\n SampleConfig,\n SamplerEvent,\n SamplerListener,\n SamplerState,\n StanRun,\n} from \"../types\";\n\ntype Action =\n | { type: \"compile:start\" }\n | { type: \"compile:done\"; modelId: string; mainJsUrl: string }\n | { type: \"compile:error\"; error: string }\n | { type: \"sample:start\" }\n | { type: \"sample:progress\"; progress: Progress }\n | { type: \"sample:done\"; run: StanRun }\n | { type: \"sample:error\"; error: string }\n | { type: \"reset\" };\n\nconst initialState: SamplerState = {\n compileStatus: \"idle\",\n sampleStatus: \"idle\",\n compileError: null,\n sampleError: null,\n progress: null,\n latestRun: null,\n consoleMessages: [],\n modelId: null,\n mainJsUrl: null,\n};\n\nconst reducer = (state: SamplerState, action: Action): SamplerState => {\n switch (action.type) {\n case \"compile:start\":\n return {\n ...state,\n compileStatus: \"compiling\",\n compileError: null,\n sampleStatus: \"idle\",\n sampleError: null,\n progress: null,\n modelId: null,\n mainJsUrl: null,\n };\n case \"compile:done\":\n return {\n ...state,\n compileStatus: \"ready\",\n modelId: action.modelId,\n mainJsUrl: action.mainJsUrl,\n };\n case \"compile:error\":\n return {\n ...state,\n compileStatus: \"error\",\n compileError: action.error,\n };\n case \"sample:start\":\n return {\n ...state,\n sampleStatus: \"sampling\",\n sampleError: null,\n progress: null,\n latestRun: null,\n consoleMessages: [],\n };\n case \"sample:progress\":\n return { ...state, progress: action.progress };\n case \"sample:done\":\n return {\n ...state,\n sampleStatus: \"done\",\n latestRun: action.run,\n consoleMessages: action.run.consoleMessages,\n };\n case \"sample:error\":\n return { ...state, sampleStatus: \"error\", sampleError: action.error };\n case \"reset\":\n return initialState;\n default:\n return state;\n }\n};\n\nexport interface UseStanWasmSamplerReturn {\n state: SamplerState;\n compile: (stanCode: string) => Promise<void>;\n sample: (config: SampleConfig, listener?: SamplerListener) => Promise<StanRun>;\n cancel: () => void;\n}\n\nexport function useStanWasmSampler(opts: StanSamplerOptions): UseStanWasmSamplerReturn {\n const [state, dispatch] = useReducer(reducer, initialState);\n const samplerRef = useRef<StanSampler | null>(null);\n const { compileServerUrl, passcode } = opts;\n const workerUrl = opts.workerUrl ?? REACT_FALLBACK_WORKER_URL;\n\n useEffect(() => {\n const sampler = new StanSampler({ compileServerUrl, passcode, workerUrl });\n samplerRef.current = sampler;\n return () => {\n sampler.cancel();\n if (samplerRef.current === sampler) {\n samplerRef.current = null;\n }\n };\n }, [compileServerUrl, passcode, workerUrl]);\n\n const compile = useCallback(async (stanCode: string) => {\n const sampler = samplerRef.current;\n if (!sampler) throw new Error(\"Sampler not yet initialised\");\n dispatch({ type: \"compile:start\" });\n try {\n const result = await sampler.compile(stanCode);\n dispatch({\n type: \"compile:done\",\n modelId: result.modelId,\n mainJsUrl: result.mainJsUrl,\n });\n } catch (err) {\n dispatch({\n type: \"compile:error\",\n error: err instanceof Error ? err.message : String(err),\n });\n throw err;\n }\n }, []);\n\n const sample = useCallback(async (config: SampleConfig, listener?: SamplerListener) => {\n const sampler = samplerRef.current;\n if (!sampler) throw new Error(\"Sampler not yet initialised\");\n dispatch({ type: \"sample:start\" });\n const wrappedListener: SamplerListener = (event: SamplerEvent) => {\n if (event.type === \"progress\") {\n dispatch({ type: \"sample:progress\", progress: event.report });\n }\n listener?.(event);\n };\n try {\n const run = await sampler.sample(config, wrappedListener);\n dispatch({ type: \"sample:done\", run });\n return run;\n } catch (err) {\n dispatch({\n type: \"sample:error\",\n error: err instanceof Error ? err.message : String(err),\n });\n throw err;\n }\n }, []);\n\n const cancel = useCallback(() => {\n samplerRef.current?.cancel();\n dispatch({ type: \"reset\" });\n }, []);\n\n return { state, compile, sample, cancel };\n}\n\nexport type { ConsoleMessage, SamplerState };\n"],"mappings":"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","names":[]}
|