concept-collection / stan-web-ide
stan-web-ide / src / stan / settings.ts
53 lines · 1.8 KBBlameHistoryRaw
1// The Stan compilation server: compiling .stan source to WebAssembly needs a
2// server (stan-wasm-wasi; see the README). The URL is a user setting
3// persisted in localStorage, shared by all projects.
4//
5// The default is the hosted instance on fly.io. It allows any origin (CORS),
6// caches compiled models by source hash, and auto-stops when idle — the
7// first compile after an idle period pays a ~30 s cold start.
9const SERVER_URL_KEY = 'stan-web-ide.compileServerUrl';
11export const DEFAULT_SERVER_URL = 'https://stan-wasm-wasi.fly.dev';
12export const LOCAL_SERVER_DOCKER_COMMAND =
13 'docker build -t stan-wasm-wasi https://github.com/magland/stan-wasm-wasi.git && docker run --rm -p 8083:8080 stan-wasm-wasi';
15type Listener = (url: string) => void;
16const listeners = new Set<Listener>();
18export function getServerUrl(): string {
19 return localStorage.getItem(SERVER_URL_KEY) || DEFAULT_SERVER_URL;
22export function setServerUrl(url: string): void {
23 const trimmed = url.trim().replace(/\/+$/, '');
24 if (trimmed) {
25 localStorage.setItem(SERVER_URL_KEY, trimmed);
26 } else {
27 localStorage.removeItem(SERVER_URL_KEY);
28 }
29 for (const listener of listeners) {
30 listener(getServerUrl());
31 }
34export function onDidChangeServerUrl(listener: Listener): { dispose(): void } {
35 listeners.add(listener);
36 return { dispose: () => listeners.delete(listener) };
39/** GET {serverUrl}/probe — true when the compile server is reachable. */
40export async function probeServer(url: string): Promise<boolean> {
41 if (!url.startsWith('http://') && !url.startsWith('https://')) {
42 return false;
43 }
44 try {
45 const controller = new AbortController();
46 const timer = setTimeout(() => controller.abort(), 5000);
47 const response = await fetch(`${url}/probe`, { signal: controller.signal });
48 clearTimeout(timer);
49 return response.ok;
50 } catch {
51 return false;
52 }