@filamind-app/core 0.1.1 → 0.1.2
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/README.md +1 -0
- package/dist/index.d.ts +32 -1
- package/dist/index.js +81 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,6 +16,7 @@ The shared foundation of the FilaMind suite — **framework-agnostic TypeScript*
|
|
|
16
16
|
| `state/printer.ts` | `PrinterState` — merge-patch from `notify_status_update`, **1 s coalescing + `motion_report` fast-path** |
|
|
17
17
|
| `moonraker/connector.ts` | the backend-agnostic `Connector` seam (Moonraker first; remote/others later) |
|
|
18
18
|
| `moonraker/client.ts` | `MoonrakerClient` — reconnecting JSON-RPC WS (**injectable socket**, backoff **+ jitter + max-attempts**), id-correlated, notify fan-out, re-subscribe on reconnect, **REST file channel** (`upload`/`download`) |
|
|
19
|
+
| `moonraker/discovery.ts` | **zero-config endpoint discovery** — `resolveMoonrakerUrl()` races candidate endpoints (same-origin proxy / direct `:7125` / localhost) → first to open wins; runtime `override` short-circuits. Socket-injectable |
|
|
19
20
|
| `moonraker/subscriptions.ts` | the **versioned** canonical subscription contract — `NARROW_STATUS` / `FULL_CONTROL` tiers + `tier()` |
|
|
20
21
|
| `printer/klippy.ts` | the Klippy lifecycle (`ready`/`startup`/`shutdown`/`error`/`disconnected`) — tracked apart from the socket so a FIRMWARE_RESTART re-seeds instead of showing stale-as-live |
|
|
21
22
|
| `printer/prompt-parser.ts` | parses Klipper's `// action:prompt_*` protocol into structured modal dialogs (`PromptParser`) |
|
package/dist/index.d.ts
CHANGED
|
@@ -143,6 +143,37 @@ declare class MoonrakerClient implements Connector {
|
|
|
143
143
|
private onMessage;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
/** A minimal view of `location` — the DOM Location satisfies it; tests pass a plain object. */
|
|
147
|
+
interface LocationLike {
|
|
148
|
+
protocol?: string;
|
|
149
|
+
hostname?: string;
|
|
150
|
+
}
|
|
151
|
+
interface DiscoveryOptions {
|
|
152
|
+
/** Explicit runtime override (e.g. from settings). If set, it wins immediately — no probing. */
|
|
153
|
+
override?: string;
|
|
154
|
+
/** Candidate ws(s):// URLs to race. If omitted, they are derived from `location`. */
|
|
155
|
+
candidates?: string[];
|
|
156
|
+
/** Overall budget before discovery gives up (ms). Default 3000. */
|
|
157
|
+
timeoutMs?: number;
|
|
158
|
+
/** Injectable socket factory (tests / non-DOM). Default: `new WebSocket`. */
|
|
159
|
+
wsFactory?: (url: string) => WebSocketLike;
|
|
160
|
+
/** Source for deriving candidates. Default: `globalThis.location`. */
|
|
161
|
+
location?: LocationLike;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Ordered, de-duplicated candidate endpoints:
|
|
165
|
+
* 1. same-origin `/websocket` (the suite deploy reverse-proxies Moonraker here),
|
|
166
|
+
* 2. the page host on Moonraker's default `:7125` (direct, no proxy),
|
|
167
|
+
* 3. `localhost:7125` (on-printer / Tauri webview, whose origin is `tauri.localhost`).
|
|
168
|
+
*/
|
|
169
|
+
declare function deriveCandidates(location?: LocationLike): string[];
|
|
170
|
+
/**
|
|
171
|
+
* Resolve a reachable Moonraker WebSocket URL. `override` wins immediately; otherwise the
|
|
172
|
+
* candidates are raced and the first socket to open wins (the rest are closed). Rejects if
|
|
173
|
+
* none open within `timeoutMs`.
|
|
174
|
+
*/
|
|
175
|
+
declare function resolveMoonrakerUrl(opts?: DiscoveryOptions): Promise<string>;
|
|
176
|
+
|
|
146
177
|
declare const SUBSCRIPTION_CONTRACT_VERSION = 1;
|
|
147
178
|
/** Status-only tier (farm overview / ambient screen): the minimum to show state + progress. */
|
|
148
179
|
declare const NARROW_STATUS: SubscriptionMap;
|
|
@@ -512,4 +543,4 @@ declare function applySettings(s: UserSettings, el?: {
|
|
|
512
543
|
dir: 'ltr' | 'rtl';
|
|
513
544
|
};
|
|
514
545
|
|
|
515
|
-
export { type AgentAllow, type AgentEvent, type BackendMessage, type Catalog, CommandSender, type CommandSenderOptions, type ConnectionState, type Connector, type ConnectorCallbacks, DEFAULT_LOCALE, DEFAULT_SETTINGS, DEFAULT_THEME, FILAMIND_COMMAND_EVENT, FULL_CONTROL, FilaMindSession, type IdentifyInfo, type KlippyState, LOCALES, type Listener, type LocaleMeta, type LogEntry, type LogLevel, Logger, MoonrakerClient, type MoonrakerClientOptions, NARROW_STATUS, NULL_LOGGER, Observable, type Params, type PluralCategory, type PrinterObjects, PrinterState, type PromptButton, type PromptDialog, type PromptEvent, PromptParser, REMOTE_MESSAGE_LEVELS, REMOTE_VIEWS, RTL_LOCALES, type RemoteCommand, type RemoteMessageLevel, type RemoteView, type RestorePoint, RestorePoints, type RestoreStore, SETTINGS_VERSION, SUBSCRIPTION_CONTRACT_VERSION, type SessionOptions, type SettingsPersistence, SettingsStore, type Source, type Stamped, type SubscriptionMap, type SubscriptionTier, type SurfaceTarget, type ThemeName, type ThemeTokens, Translator, UNKNOWN, type UserSettings, type WebSocketLike, type WidgetDefinition, WriteArbiter, type WriteGuard, WriteRefused, _resetRegistry, aggregateSubscriptions, applySettings, applyTheme, deepMerge, deriveKlippyState, deriveMachineId, fnv1a, freshness, getWidget, getWidgets, handleAgentCommand, isKlippyLive, isRtl, isStale, localStoragePersistence, localeMeta, memoryPersistence, memoryRestoreStore, mergeSubscriptions, migrate, moonrakerDbPersistence, parseAgentEvent, parseCommand, pluralCategory, registerWidget, resolveMessage, roamSettings, stamp, themeToCssVars, themes, tier, translate };
|
|
546
|
+
export { type AgentAllow, type AgentEvent, type BackendMessage, type Catalog, CommandSender, type CommandSenderOptions, type ConnectionState, type Connector, type ConnectorCallbacks, DEFAULT_LOCALE, DEFAULT_SETTINGS, DEFAULT_THEME, type DiscoveryOptions, FILAMIND_COMMAND_EVENT, FULL_CONTROL, FilaMindSession, type IdentifyInfo, type KlippyState, LOCALES, type Listener, type LocaleMeta, type LocationLike, type LogEntry, type LogLevel, Logger, MoonrakerClient, type MoonrakerClientOptions, NARROW_STATUS, NULL_LOGGER, Observable, type Params, type PluralCategory, type PrinterObjects, PrinterState, type PromptButton, type PromptDialog, type PromptEvent, PromptParser, REMOTE_MESSAGE_LEVELS, REMOTE_VIEWS, RTL_LOCALES, type RemoteCommand, type RemoteMessageLevel, type RemoteView, type RestorePoint, RestorePoints, type RestoreStore, SETTINGS_VERSION, SUBSCRIPTION_CONTRACT_VERSION, type SessionOptions, type SettingsPersistence, SettingsStore, type Source, type Stamped, type SubscriptionMap, type SubscriptionTier, type SurfaceTarget, type ThemeName, type ThemeTokens, Translator, UNKNOWN, type UserSettings, type WebSocketLike, type WidgetDefinition, WriteArbiter, type WriteGuard, WriteRefused, _resetRegistry, aggregateSubscriptions, applySettings, applyTheme, deepMerge, deriveCandidates, deriveKlippyState, deriveMachineId, fnv1a, freshness, getWidget, getWidgets, handleAgentCommand, isKlippyLive, isRtl, isStale, localStoragePersistence, localeMeta, memoryPersistence, memoryRestoreStore, mergeSubscriptions, migrate, moonrakerDbPersistence, parseAgentEvent, parseCommand, pluralCategory, registerWidget, resolveMessage, resolveMoonrakerUrl, roamSettings, stamp, themeToCssVars, themes, tier, translate };
|
package/dist/index.js
CHANGED
|
@@ -270,6 +270,85 @@ function xhrUpload(url, form, onProgress) {
|
|
|
270
270
|
});
|
|
271
271
|
}
|
|
272
272
|
|
|
273
|
+
// src/moonraker/discovery.ts
|
|
274
|
+
var defaultWsFactory2 = (url) => new WebSocket(url);
|
|
275
|
+
function deriveCandidates(location) {
|
|
276
|
+
const loc = location ?? globalThis.location ?? {};
|
|
277
|
+
const wsProto = loc.protocol === "https:" ? "wss" : "ws";
|
|
278
|
+
const host = loc.hostname && loc.hostname.length > 0 ? loc.hostname : "localhost";
|
|
279
|
+
return [
|
|
280
|
+
.../* @__PURE__ */ new Set([
|
|
281
|
+
`${wsProto}://${host}/websocket`,
|
|
282
|
+
`${wsProto}://${host}:7125/websocket`,
|
|
283
|
+
`ws://localhost:7125/websocket`
|
|
284
|
+
])
|
|
285
|
+
];
|
|
286
|
+
}
|
|
287
|
+
function resolveMoonrakerUrl(opts = {}) {
|
|
288
|
+
const override = opts.override?.trim();
|
|
289
|
+
if (override) return Promise.resolve(override);
|
|
290
|
+
const candidates = opts.candidates ?? deriveCandidates(opts.location);
|
|
291
|
+
if (candidates.length === 0) {
|
|
292
|
+
return Promise.reject(new Error("moonraker discovery: no candidate endpoints"));
|
|
293
|
+
}
|
|
294
|
+
const makeWs = opts.wsFactory ?? defaultWsFactory2;
|
|
295
|
+
const timeoutMs = opts.timeoutMs ?? 3e3;
|
|
296
|
+
return new Promise((resolve, reject) => {
|
|
297
|
+
let settled = false;
|
|
298
|
+
let remaining = candidates.length;
|
|
299
|
+
const sockets = [];
|
|
300
|
+
const timer = setTimeout(finishFail, timeoutMs);
|
|
301
|
+
function cleanup() {
|
|
302
|
+
clearTimeout(timer);
|
|
303
|
+
for (const s of sockets) {
|
|
304
|
+
s.onopen = null;
|
|
305
|
+
s.onerror = null;
|
|
306
|
+
s.onclose = null;
|
|
307
|
+
try {
|
|
308
|
+
s.close();
|
|
309
|
+
} catch {
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
function finishOk(url) {
|
|
314
|
+
if (settled) return;
|
|
315
|
+
settled = true;
|
|
316
|
+
cleanup();
|
|
317
|
+
resolve(url);
|
|
318
|
+
}
|
|
319
|
+
function finishFail() {
|
|
320
|
+
if (settled) return;
|
|
321
|
+
settled = true;
|
|
322
|
+
cleanup();
|
|
323
|
+
reject(new Error(`moonraker discovery: no endpoint responded (${candidates.join(", ")})`));
|
|
324
|
+
}
|
|
325
|
+
function lose() {
|
|
326
|
+
remaining -= 1;
|
|
327
|
+
if (remaining <= 0) finishFail();
|
|
328
|
+
}
|
|
329
|
+
for (const url of candidates) {
|
|
330
|
+
let s;
|
|
331
|
+
try {
|
|
332
|
+
s = makeWs(url);
|
|
333
|
+
} catch {
|
|
334
|
+
lose();
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
sockets.push(s);
|
|
338
|
+
let done = false;
|
|
339
|
+
const fail = () => {
|
|
340
|
+
if (!done) {
|
|
341
|
+
done = true;
|
|
342
|
+
lose();
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
s.onopen = () => finishOk(url);
|
|
346
|
+
s.onerror = fail;
|
|
347
|
+
s.onclose = fail;
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
|
|
273
352
|
// src/moonraker/subscriptions.ts
|
|
274
353
|
var SUBSCRIPTION_CONTRACT_VERSION = 1;
|
|
275
354
|
var NARROW_STATUS = {
|
|
@@ -1172,6 +1251,7 @@ export {
|
|
|
1172
1251
|
applySettings,
|
|
1173
1252
|
applyTheme,
|
|
1174
1253
|
deepMerge,
|
|
1254
|
+
deriveCandidates,
|
|
1175
1255
|
deriveKlippyState,
|
|
1176
1256
|
deriveMachineId,
|
|
1177
1257
|
fnv1a,
|
|
@@ -1194,6 +1274,7 @@ export {
|
|
|
1194
1274
|
pluralCategory,
|
|
1195
1275
|
registerWidget,
|
|
1196
1276
|
resolveMessage,
|
|
1277
|
+
resolveMoonrakerUrl,
|
|
1197
1278
|
roamSettings,
|
|
1198
1279
|
stamp,
|
|
1199
1280
|
themeToCssVars,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@filamind-app/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Shared foundation for the FilaMind suite — Moonraker client, reactive printer state, provenance-stamped values, design tokens, and the widget/plugin registry. Framework-agnostic TypeScript.",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"repository": {
|