@mudlet/mudlet-web 0.3.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 +338 -0
- package/README.md +150 -0
- package/dist-lib/App.d.ts +1 -0
- package/dist-lib/MudletWebApp.d.ts +11 -0
- package/dist-lib/ProfileSession.d.ts +15 -0
- package/dist-lib/assets/mapParser.worker-t-3rd1zR.js +9 -0
- package/dist-lib/branding.d.ts +213 -0
- package/dist-lib/core/EventBus.d.ts +29 -0
- package/dist-lib/db/sqliteClient.d.ts +25 -0
- package/dist-lib/hooks/useEngines.d.ts +12 -0
- package/dist-lib/hooks/useMudSession.d.ts +10 -0
- package/dist-lib/hooks/useOutput.d.ts +17 -0
- package/dist-lib/hooks/useViewportMode.d.ts +14 -0
- package/dist-lib/import/applyMudletProfile.d.ts +57 -0
- package/dist-lib/import/collectProfileExport.d.ts +16 -0
- package/dist-lib/import/defaultPackages.d.ts +81 -0
- package/dist-lib/import/defaults/mudlet-mapper.xml +13023 -0
- package/dist-lib/import/defaults/run-lua-code.mpackage +0 -0
- package/dist-lib/import/mudletHost.d.ts +67 -0
- package/dist-lib/import/mudletLink.d.ts +34 -0
- package/dist-lib/import/mudletProfileExport.d.ts +49 -0
- package/dist-lib/import/mudletProfileImport.d.ts +71 -0
- package/dist-lib/import/mudletVariables.d.ts +49 -0
- package/dist-lib/import/mudletWriteback.d.ts +12 -0
- package/dist-lib/import/mudletXmlExport.d.ts +16 -0
- package/dist-lib/import/mudletXmlImport.d.ts +21 -0
- package/dist-lib/import/packageInstaller.d.ts +72 -0
- package/dist-lib/import/packageRepository.d.ts +54 -0
- package/dist-lib/import/remotePackageInstall.d.ts +52 -0
- package/dist-lib/index.d.ts +30 -0
- package/dist-lib/index.js +42307 -0
- package/dist-lib/logging/SessionLogger.d.ts +41 -0
- package/dist-lib/main.d.ts +2 -0
- package/dist-lib/map/MapSelectionOverlay.d.ts +15 -0
- package/dist-lib/map/MapStore.d.ts +1067 -0
- package/dist-lib/map/MudixMapReader.d.ts +90 -0
- package/dist-lib/map/MudletHighlightOverlay.d.ts +18 -0
- package/dist-lib/map/mapImageExport.d.ts +26 -0
- package/dist-lib/map/mapParser.worker.d.ts +1 -0
- package/dist-lib/map/mapParserClient.d.ts +35 -0
- package/dist-lib/map/pathfinding.d.ts +52 -0
- package/dist-lib/map/xmlMapImport.d.ts +28 -0
- package/dist-lib/mud/MudSession.d.ts +236 -0
- package/dist-lib/mud/PatternEngine.d.ts +28 -0
- package/dist-lib/mud/aliases/AliasEngine.d.ts +15 -0
- package/dist-lib/mud/connection/LineAssembler.d.ts +84 -0
- package/dist-lib/mud/connection/MudClient.d.ts +268 -0
- package/dist-lib/mud/connection/PingTracker.d.ts +28 -0
- package/dist-lib/mud/connection/TelnetNegotiator.d.ts +188 -0
- package/dist-lib/mud/connection/telnetDebug.d.ts +54 -0
- package/dist-lib/mud/events.d.ts +160 -0
- package/dist-lib/mud/keybindings/KeyEngine.d.ts +36 -0
- package/dist-lib/mud/keybindings/browserReservedKeys.d.ts +45 -0
- package/dist-lib/mud/keybindings/qtKeys.d.ts +33 -0
- package/dist-lib/mud/protocol/charset.d.ts +105 -0
- package/dist-lib/mud/protocol/constants.d.ts +116 -0
- package/dist-lib/mud/protocol/echo.d.ts +63 -0
- package/dist-lib/mud/protocol/gmcp.d.ts +28 -0
- package/dist-lib/mud/protocol/index.d.ts +11 -0
- package/dist-lib/mud/protocol/mccp.d.ts +18 -0
- package/dist-lib/mud/protocol/mnes.d.ts +83 -0
- package/dist-lib/mud/protocol/msdp.d.ts +19 -0
- package/dist-lib/mud/protocol/msp.d.ts +47 -0
- package/dist-lib/mud/protocol/mssp.d.ts +25 -0
- package/dist-lib/mud/protocol/mxp.d.ts +188 -0
- package/dist-lib/mud/protocol/naws.d.ts +7 -0
- package/dist-lib/mud/replay/ReplayPlayer.d.ts +31 -0
- package/dist-lib/mud/replay/ReplayRecorder.d.ts +18 -0
- package/dist-lib/mud/replay/replayFormat.d.ts +49 -0
- package/dist-lib/mud/text/Console.d.ts +183 -0
- package/dist-lib/mud/text/FormatState.d.ts +256 -0
- package/dist-lib/mud/text/ansiEscapes.d.ts +88 -0
- package/dist-lib/mud/text/cellRender.d.ts +21 -0
- package/dist-lib/mud/text/colorParsers.d.ts +54 -0
- package/dist-lib/mud/text/colors.d.ts +31 -0
- package/dist-lib/mud/text/controlCharacterMode.d.ts +13 -0
- package/dist-lib/mud/text/controlChars.d.ts +31 -0
- package/dist-lib/mud/text/hyperlinkConfig.d.ts +164 -0
- package/dist-lib/mud/text/hyperlinkVisibility.d.ts +37 -0
- package/dist-lib/mud/text/oscLinkManager.d.ts +35 -0
- package/dist-lib/mud/text/wcwidth.d.ts +44 -0
- package/dist-lib/mud/text/xterm256.d.ts +2 -0
- package/dist-lib/mud/timers/TimerEngine.d.ts +61 -0
- package/dist-lib/mud/triggers/ChunkProcessor.d.ts +11 -0
- package/dist-lib/mud/triggers/TriggerEngine.d.ts +188 -0
- package/dist-lib/mud/triggers/pcre/Pcre2.d.ts +26 -0
- package/dist-lib/scripting/EngineHost.d.ts +152 -0
- package/dist-lib/scripting/GlobalEventChannel.d.ts +36 -0
- package/dist-lib/scripting/IScriptingRuntime.d.ts +95 -0
- package/dist-lib/scripting/MapOpenNotifier.d.ts +19 -0
- package/dist-lib/scripting/ScriptingAPI.d.ts +1691 -0
- package/dist-lib/scripting/ScriptingEngine.d.ts +806 -0
- package/dist-lib/scripting/StopwatchManager.d.ts +94 -0
- package/dist-lib/scripting/heldModifiers.d.ts +3 -0
- package/dist-lib/scripting/http/HttpService.d.ts +23 -0
- package/dist-lib/scripting/lua/LuaRuntime.d.ts +190 -0
- package/dist-lib/scripting/lua/bindings/automation.d.ts +10 -0
- package/dist-lib/scripting/lua/bindings/commandLine.d.ts +11 -0
- package/dist-lib/scripting/lua/bindings/context.d.ts +87 -0
- package/dist-lib/scripting/lua/bindings/cursor.d.ts +10 -0
- package/dist-lib/scripting/lua/bindings/diagnostics.d.ts +9 -0
- package/dist-lib/scripting/lua/bindings/map.d.ts +14 -0
- package/dist-lib/scripting/lua/bindings/media.d.ts +24 -0
- package/dist-lib/scripting/lua/bindings/output.d.ts +10 -0
- package/dist-lib/scripting/lua/bindings/packages.d.ts +10 -0
- package/dist-lib/scripting/lua/bindings/session.d.ts +16 -0
- package/dist-lib/scripting/lua/bindings/textEdit.d.ts +9 -0
- package/dist-lib/scripting/lua/bindings/userWindows.d.ts +11 -0
- package/dist-lib/scripting/lua/bindings/window.d.ts +10 -0
- package/dist-lib/scripting/lua/imageSize.d.ts +4 -0
- package/dist-lib/scripting/lua/luaCompletions.d.ts +9 -0
- package/dist-lib/scripting/lua/mudlet-lua/generic-mapper/generic_mapper.mpackage +0 -0
- package/dist-lib/scripting/lua/rex.d.ts +3 -0
- package/dist-lib/scripting/lua/sqlRowEncoder.d.ts +1 -0
- package/dist-lib/scripting/lua/yajl.d.ts +11 -0
- package/dist-lib/scripting/profilesPresence.d.ts +50 -0
- package/dist-lib/scripting/vfs/ProfileVFS.d.ts +62 -0
- package/dist-lib/scripting/vfs/cssRewrite.d.ts +21 -0
- package/dist-lib/scripting/vfs/folderHandleStore.d.ts +16 -0
- package/dist-lib/scripting/vfs/folderSync.d.ts +59 -0
- package/dist-lib/scripting/vfs/htmlRewrite.d.ts +26 -0
- package/dist-lib/scripting/vfs/vfsBridge.d.ts +16 -0
- package/dist-lib/services/cloudflare.d.ts +54 -0
- package/dist-lib/storage/appStore.d.ts +132 -0
- package/dist-lib/storage/crossTabSync.d.ts +3 -0
- package/dist-lib/storage/debouncedStorage.d.ts +18 -0
- package/dist-lib/storage/hooks.d.ts +17 -0
- package/dist-lib/storage/index.d.ts +4 -0
- package/dist-lib/storage/logExport.d.ts +32 -0
- package/dist-lib/storage/logStorage.d.ts +45 -0
- package/dist-lib/storage/mapStorage.d.ts +2 -0
- package/dist-lib/storage/profileVfsData.d.ts +47 -0
- package/dist-lib/storage/schema.d.ts +638 -0
- package/dist-lib/styles.css +2 -0
- package/dist-lib/ui/AboutModal.d.ts +8 -0
- package/dist-lib/ui/BrandLoginFields.d.ts +25 -0
- package/dist-lib/ui/BrandLoginScreen.d.ts +11 -0
- package/dist-lib/ui/CharLoginModal.d.ts +32 -0
- package/dist-lib/ui/CmdLineMenuRegistry.d.ts +27 -0
- package/dist-lib/ui/CodeEditorPreview.d.ts +19 -0
- package/dist-lib/ui/CommandBar.d.ts +17 -0
- package/dist-lib/ui/ConnectionFormModal.d.ts +13 -0
- package/dist-lib/ui/ConnectionGrid.d.ts +18 -0
- package/dist-lib/ui/ConnectionScreen.d.ts +14 -0
- package/dist-lib/ui/FileBrowserModal.d.ts +20 -0
- package/dist-lib/ui/FilePickerModal.d.ts +21 -0
- package/dist-lib/ui/FolderPermissionScreen.d.ts +16 -0
- package/dist-lib/ui/JsonPreview.d.ts +15 -0
- package/dist-lib/ui/LogBrowserModal.d.ts +7 -0
- package/dist-lib/ui/MapEditorModal.d.ts +9 -0
- package/dist-lib/ui/MarkdownPreview.d.ts +15 -0
- package/dist-lib/ui/MergeConflictModal.d.ts +17 -0
- package/dist-lib/ui/ModuleResolveModal.d.ts +22 -0
- package/dist-lib/ui/MouseEventRegistry.d.ts +31 -0
- package/dist-lib/ui/ProfileBusyScreen.d.ts +12 -0
- package/dist-lib/ui/ProfileExportModal.d.ts +7 -0
- package/dist-lib/ui/ProxyInfoModal.d.ts +6 -0
- package/dist-lib/ui/ProxyWhyModal.d.ts +6 -0
- package/dist-lib/ui/ProxyWizardModal.d.ts +6 -0
- package/dist-lib/ui/QuickOpenPalette.d.ts +8 -0
- package/dist-lib/ui/ResizableModal.d.ts +17 -0
- package/dist-lib/ui/ScriptingDocsModal.d.ts +12 -0
- package/dist-lib/ui/SettingsModal.d.ts +9 -0
- package/dist-lib/ui/Toolbar.d.ts +29 -0
- package/dist-lib/ui/bufferWords.d.ts +38 -0
- package/dist-lib/ui/buttons/ButtonsBar.d.ts +21 -0
- package/dist-lib/ui/cmdline/CommandLineManager.d.ts +97 -0
- package/dist-lib/ui/cmdline/CommandLineOverlay.d.ts +8 -0
- package/dist-lib/ui/codemirror/theme.d.ts +5 -0
- package/dist-lib/ui/commandHistory.d.ts +31 -0
- package/dist-lib/ui/components/Button.d.ts +9 -0
- package/dist-lib/ui/components/ConfirmDialog.d.ts +29 -0
- package/dist-lib/ui/components/ContextMenu.d.ts +9 -0
- package/dist-lib/ui/components/FontPicker.d.ts +9 -0
- package/dist-lib/ui/components/FormField.d.ts +16 -0
- package/dist-lib/ui/components/HelpTip.d.ts +7 -0
- package/dist-lib/ui/components/Input.d.ts +6 -0
- package/dist-lib/ui/components/Toggle.d.ts +10 -0
- package/dist-lib/ui/components/index.d.ts +9 -0
- package/dist-lib/ui/components/useModalFocus.d.ts +18 -0
- package/dist-lib/ui/labels/LabelManager.d.ts +220 -0
- package/dist-lib/ui/labels/LabelOverlay.d.ts +9 -0
- package/dist-lib/ui/labels/backgroundImageSize.d.ts +10 -0
- package/dist-lib/ui/labels/cursorShapes.d.ts +6 -0
- package/dist-lib/ui/labels/gifMovie.d.ts +100 -0
- package/dist-lib/ui/labels/qtCss.d.ts +57 -0
- package/dist-lib/ui/layout/ContentLayout.d.ts +19 -0
- package/dist-lib/ui/layout/DockArea.d.ts +14 -0
- package/dist-lib/ui/layout/DockedPanel.d.ts +13 -0
- package/dist-lib/ui/layout/FloatingWindowLayer.d.ts +10 -0
- package/dist-lib/ui/layout/MobileLayout.d.ts +22 -0
- package/dist-lib/ui/layout/PopoutWindow.d.ts +35 -0
- package/dist-lib/ui/layout/ScriptWindow.d.ts +29 -0
- package/dist-lib/ui/layout/SplitGroupPanel.d.ts +17 -0
- package/dist-lib/ui/layout/TabGroupPanel.d.ts +12 -0
- package/dist-lib/ui/layout/WindowContextMenu.d.ts +11 -0
- package/dist-lib/ui/layout/dockDetect.d.ts +26 -0
- package/dist-lib/ui/layout/overlayLayerOrder.d.ts +71 -0
- package/dist-lib/ui/markdown.d.ts +1 -0
- package/dist-lib/ui/output/CaretReviewPanel.d.ts +22 -0
- package/dist-lib/ui/output/OutputArea.d.ts +9 -0
- package/dist-lib/ui/output/OutputContextMenu.d.ts +23 -0
- package/dist-lib/ui/output/OutputRenderer.d.ts +64 -0
- package/dist-lib/ui/output/ScreenReaderLog.d.ts +23 -0
- package/dist-lib/ui/output/StickyOutputPanel.d.ts +28 -0
- package/dist-lib/ui/output/backgroundImageStyle.d.ts +17 -0
- package/dist-lib/ui/output/caretMode.d.ts +40 -0
- package/dist-lib/ui/output/linkNavigation.d.ts +29 -0
- package/dist-lib/ui/output/osc8Menu.d.ts +16 -0
- package/dist-lib/ui/output/outputCopy.d.ts +15 -0
- package/dist-lib/ui/preventPinchZoom.d.ts +1 -0
- package/dist-lib/ui/scrollbox/ScrollBoxManager.d.ts +62 -0
- package/dist-lib/ui/scrollbox/ScrollBoxOverlay.d.ts +25 -0
- package/dist-lib/ui/sound/SoundManager.d.ts +149 -0
- package/dist-lib/ui/sound/closedCaption.d.ts +37 -0
- package/dist-lib/ui/textedit/TextEditManager.d.ts +56 -0
- package/dist-lib/ui/tts/TtsManager.d.ts +68 -0
- package/dist-lib/ui/useBrandLogin.d.ts +19 -0
- package/dist-lib/ui/useCommandHistory.d.ts +7 -0
- package/dist-lib/ui/video/VideoManager.d.ts +56 -0
- package/dist-lib/ui/windows/ScriptEditorModal.d.ts +13 -0
- package/dist-lib/ui/windows/WindowManager.d.ts +694 -0
- package/dist-lib/ui/windows/panels/HtmlPanel.d.ts +27 -0
- package/dist-lib/ui/windows/panels/LuaEditor.d.ts +14 -0
- package/dist-lib/ui/windows/panels/MapPanel.d.ts +8 -0
- package/dist-lib/ui/windows/panels/PackageRepositoryModal.d.ts +18 -0
- package/dist-lib/ui/windows/panels/ScriptEditorPanel.d.ts +24 -0
- package/dist-lib/ui/windows/panels/ScriptSearch.d.ts +12 -0
- package/dist-lib/ui/windows/panels/TextPanel.d.ts +35 -0
- package/dist-lib/ui/windows/panels/VariablesView.d.ts +21 -0
- package/dist-lib/ui/windows/panels/VfsModulePickerModal.d.ts +8 -0
- package/dist-lib/ui/windows/panels/WindowCmdLine.d.ts +23 -0
- package/dist-lib/ui/windows/types.d.ts +145 -0
- package/dist-lib/utils/documentTitle.d.ts +33 -0
- package/dist-lib/utils/fontLoader.d.ts +52 -0
- package/dist-lib/utils/profileLock.d.ts +26 -0
- package/dist-lib/utils/sessionCredentials.d.ts +16 -0
- package/dist-lib/version.d.ts +39 -0
- package/dist-lib/vfs-sw.js +131 -0
- package/dist-lib/vite.d.ts +2 -0
- package/dist-lib/vite.js +154 -0
- package/package.json +93 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-tab view of which profiles are open and which are connected — backs
|
|
3
|
+
* Mudlet's `getProfiles()`. mudix runs one profile per browser tab, so two
|
|
4
|
+
* cross-tab signals are combined:
|
|
5
|
+
*
|
|
6
|
+
* - **loaded** (open & editable): every open profile holds an exclusive Web
|
|
7
|
+
* Lock named `mudix:profile:<id>` (see profileLock.ts). `navigator.locks
|
|
8
|
+
* .query()` lists held locks across all same-origin tabs, so the held
|
|
9
|
+
* profile locks ARE the loaded set. Authoritative and crash-safe (the browser
|
|
10
|
+
* auto-releases a lock when its tab closes/crashes). Polled on a slow interval
|
|
11
|
+
* since the query is async but `getProfiles()` is a synchronous Lua call.
|
|
12
|
+
*
|
|
13
|
+
* - **connected** (playing): not observable through Web Locks, so each tab
|
|
14
|
+
* announces its own live connection state over a `BroadcastChannel`. A tab
|
|
15
|
+
* announces on connect/disconnect and answers a `query` from a newly-opened
|
|
16
|
+
* tab; `bye` on teardown clears it eagerly (a crash is caught by the loaded
|
|
17
|
+
* set dropping). The owning tab's own state is always read live.
|
|
18
|
+
*
|
|
19
|
+
* Degrades gracefully where the platform lacks these APIs (legacy browser,
|
|
20
|
+
* insecure context, or the Node test environment): no Web Locks → loaded is just
|
|
21
|
+
* this profile; no BroadcastChannel → connected is just this profile's live
|
|
22
|
+
* state. That matches the old single-profile `getProfiles()` behaviour.
|
|
23
|
+
*/
|
|
24
|
+
export declare class ProfilesPresence {
|
|
25
|
+
private readonly ownId;
|
|
26
|
+
/** This tab's live connected state, read whenever we announce. */
|
|
27
|
+
private readonly localConnected;
|
|
28
|
+
private channel;
|
|
29
|
+
private lockTimer;
|
|
30
|
+
/** Loaded profile ids from Web Locks (authoritative; always includes self). */
|
|
31
|
+
private loaded;
|
|
32
|
+
/** Last-announced connected state of OTHER tabs' profiles. */
|
|
33
|
+
private readonly remoteConnected;
|
|
34
|
+
constructor(ownId: string,
|
|
35
|
+
/** This tab's live connected state, read whenever we announce. */
|
|
36
|
+
localConnected: () => boolean, refreshMs?: number);
|
|
37
|
+
/** Broadcast this tab's current connected state to peers. Call on connect/
|
|
38
|
+
* disconnect. No-op without a channel. */
|
|
39
|
+
announce(): void;
|
|
40
|
+
/** Connection ids of all loaded profiles (best-effort snapshot, always
|
|
41
|
+
* including this profile's own id). */
|
|
42
|
+
loadedIds(): string[];
|
|
43
|
+
/** Connected state for a profile id: own → live, others → last announced
|
|
44
|
+
* (false when never announced). Callers gate this on `loaded` so a crashed
|
|
45
|
+
* tab's stale "connected" can't outlive its lock. */
|
|
46
|
+
isConnected(id: string): boolean;
|
|
47
|
+
private onMessage;
|
|
48
|
+
private refreshLoaded;
|
|
49
|
+
destroy(): void;
|
|
50
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export type VFSSource = 'folder' | 'idb';
|
|
2
|
+
export declare class ProfileVFS {
|
|
3
|
+
readonly connectionId: string;
|
|
4
|
+
readonly profilePath: string;
|
|
5
|
+
private _cwd;
|
|
6
|
+
private _fs;
|
|
7
|
+
private _handle?;
|
|
8
|
+
readonly source: VFSSource;
|
|
9
|
+
readonly folderName?: string;
|
|
10
|
+
private constructor();
|
|
11
|
+
static mount(connectionId: string): Promise<ProfileVFS>;
|
|
12
|
+
private static doMount;
|
|
13
|
+
get cwd(): string;
|
|
14
|
+
resolvePath(path: string): string;
|
|
15
|
+
exists(path: string): boolean;
|
|
16
|
+
readFile(path: string): string;
|
|
17
|
+
readBinaryFile(path: string): Uint8Array;
|
|
18
|
+
writeFile(path: string, content: string): void;
|
|
19
|
+
writeBinaryFile(path: string, data: Uint8Array): void;
|
|
20
|
+
/**
|
|
21
|
+
* The linked-folder (WebAccess / FileSystemDirectoryHandle) backend overwrites
|
|
22
|
+
* a file from offset 0 but does NOT shrink it, so writing shorter content over
|
|
23
|
+
* longer leaves stale tail bytes — silently corrupting Lua `table.save` data,
|
|
24
|
+
* JSON, and the profile XML. Removing the file first forces a fresh,
|
|
25
|
+
* correctly-sized write. IndexedDB truncates on the `w` flag correctly, so it's
|
|
26
|
+
* left untouched (no extra op per save).
|
|
27
|
+
*/
|
|
28
|
+
private clearForOverwrite;
|
|
29
|
+
appendFile(path: string, content: string): void;
|
|
30
|
+
deleteFile(path: string): void;
|
|
31
|
+
rename(oldPath: string, newPath: string): void;
|
|
32
|
+
mkdir(path: string): void;
|
|
33
|
+
rmdir(path: string): void;
|
|
34
|
+
readdir(path: string): string[];
|
|
35
|
+
stat(path: string): {
|
|
36
|
+
type: 'file' | 'dir';
|
|
37
|
+
size: number;
|
|
38
|
+
mtime: Date;
|
|
39
|
+
atime: Date;
|
|
40
|
+
} | null;
|
|
41
|
+
chdir(path: string): string | null;
|
|
42
|
+
/**
|
|
43
|
+
* Drain queued async writes to the underlying backend. For folder-backed
|
|
44
|
+
* mounts this writes RAM-cached changes through to disk; for IDB mounts
|
|
45
|
+
* it persists to IndexedDB. Safe to call on any source.
|
|
46
|
+
*/
|
|
47
|
+
flush(): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Re-walk the linked directory and rebuild the in-memory cache. Use after
|
|
50
|
+
* external edits (file added/changed in the OS file manager). No-op for
|
|
51
|
+
* IDB-backed profiles since their state is owned by the browser.
|
|
52
|
+
*
|
|
53
|
+
* Any Lua file handles opened before resync become invalid: ZenFS replaces
|
|
54
|
+
* the underlying FS instance, so subsequent reads on those handles will
|
|
55
|
+
* error. New `io.open` calls work normally.
|
|
56
|
+
*/
|
|
57
|
+
resync(): Promise<void>;
|
|
58
|
+
/** Tell the VFS service worker to drop its cached copy of a file, keyed
|
|
59
|
+
* by its path relative to the profile root (matches vfsUrlFor's scheme). */
|
|
60
|
+
private invalidate;
|
|
61
|
+
unmount(): void;
|
|
62
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ProfileVFS } from './ProfileVFS';
|
|
2
|
+
/**
|
|
3
|
+
* Map one asset reference onto the URL the service worker serves, or return
|
|
4
|
+
* null when it must be left alone (empty, or already an absolute http/data/
|
|
5
|
+
* blob/__vfs URL). Paths are resolved through the VFS (honouring its cwd and
|
|
6
|
+
* profile root) and rebased onto the profile root.
|
|
7
|
+
*
|
|
8
|
+
* Shared by the stylesheet rewriter and the label-HTML rewriter so `url(...)`
|
|
9
|
+
* in a stylesheet and `<img src>` in label rich text resolve identically.
|
|
10
|
+
*/
|
|
11
|
+
export declare function vfsRefToUrl(ref: string, connectionId: string, vfs: ProfileVFS): string | null;
|
|
12
|
+
/**
|
|
13
|
+
* Rewrite `url(<local-path>)` references in a Qt/CSS stylesheet to
|
|
14
|
+
* `url(/__vfs/<connectionId>/<path>)` so the registered service worker can
|
|
15
|
+
* serve the bytes from the connection's ProfileVFS. Already-absolute http/data/
|
|
16
|
+
* blob/__vfs URLs pass through untouched.
|
|
17
|
+
*
|
|
18
|
+
* Paths are resolved through the VFS (which honours its cwd and profile root)
|
|
19
|
+
* and rebased onto the profile root before being put into the URL.
|
|
20
|
+
*/
|
|
21
|
+
export declare function rewriteVfsUrlsInCss(css: string, connectionId: string, vfs: ProfileVFS): string;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
interface ShowDirectoryPickerOptions {
|
|
2
|
+
mode?: 'read' | 'readwrite';
|
|
3
|
+
}
|
|
4
|
+
declare global {
|
|
5
|
+
interface Window {
|
|
6
|
+
showDirectoryPicker?: (options?: ShowDirectoryPickerOptions) => Promise<FileSystemDirectoryHandle>;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export type FolderPermissionState = 'granted' | 'prompt' | 'denied' | 'unsupported';
|
|
10
|
+
export declare function isFolderLinkSupported(): boolean;
|
|
11
|
+
export declare function saveFolderHandle(connectionId: string, handle: FileSystemDirectoryHandle): Promise<void>;
|
|
12
|
+
export declare function loadFolderHandle(connectionId: string): Promise<FileSystemDirectoryHandle | null>;
|
|
13
|
+
export declare function clearFolderHandle(connectionId: string): Promise<void>;
|
|
14
|
+
export declare function checkFolderPermission(handle: FileSystemDirectoryHandle): Promise<FolderPermissionState>;
|
|
15
|
+
export declare function requestFolderPermission(handle: FileSystemDirectoryHandle): Promise<FolderPermissionState>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { readFileSync, statSync } from '@zenfs/core';
|
|
2
|
+
import type { ProfileVFS } from './ProfileVFS';
|
|
3
|
+
export type SideKind = 'local' | 'folder';
|
|
4
|
+
export interface FileEntry {
|
|
5
|
+
/** Relative path from the profile root, e.g. "scripts/foo.lua". No leading slash. */
|
|
6
|
+
path: string;
|
|
7
|
+
size: number;
|
|
8
|
+
mtimeMs: number;
|
|
9
|
+
}
|
|
10
|
+
export interface DiffResult {
|
|
11
|
+
/** Files present only in the local (IDB) side. */
|
|
12
|
+
onlyLocal: FileEntry[];
|
|
13
|
+
/** Files present only in the linked folder. */
|
|
14
|
+
onlyFolder: FileEntry[];
|
|
15
|
+
/** Files at the same path on both sides (need user resolution). */
|
|
16
|
+
conflicts: {
|
|
17
|
+
path: string;
|
|
18
|
+
local: FileEntry;
|
|
19
|
+
folder: FileEntry;
|
|
20
|
+
}[];
|
|
21
|
+
}
|
|
22
|
+
export declare function walkFolderHandle(root: FileSystemDirectoryHandle): Promise<FileEntry[]>;
|
|
23
|
+
/** Walk every file under the mounted profile, returning paths relative to the profile root. */
|
|
24
|
+
export declare function walkVfsTree(vfs: ProfileVFS): FileEntry[];
|
|
25
|
+
/**
|
|
26
|
+
* A file is considered "conflicting" if it exists at the same relative path on
|
|
27
|
+
* both sides, regardless of whether the bytes match. Comparing mtime/size is
|
|
28
|
+
* unreliable across filesystems (folder-backed mtime comes from disk,
|
|
29
|
+
* IDB-backed mtime comes from the inode index), so we let the user resolve.
|
|
30
|
+
*/
|
|
31
|
+
export declare function diffSides(local: FileEntry[], folder: FileEntry[]): DiffResult;
|
|
32
|
+
/**
|
|
33
|
+
* Copy the listed relative paths from the mounted profile into the linked
|
|
34
|
+
* folder. Used on link to materialize IDB-only files (and "use local"
|
|
35
|
+
* resolutions) before the next mount picks up the folder as the source.
|
|
36
|
+
*/
|
|
37
|
+
export declare function copyVfsToFolder(vfs: ProfileVFS, handle: FileSystemDirectoryHandle, relPaths: string[]): Promise<{
|
|
38
|
+
copied: number;
|
|
39
|
+
failed: {
|
|
40
|
+
path: string;
|
|
41
|
+
reason: string;
|
|
42
|
+
}[];
|
|
43
|
+
}>;
|
|
44
|
+
/**
|
|
45
|
+
* Side-mount a fresh IDB backend for the given connection at a temporary
|
|
46
|
+
* profile path, copy every file from the linked folder into it, then unmount.
|
|
47
|
+
* Used on unlink so the user's next mount (now IDB-backed because the handle
|
|
48
|
+
* is cleared) sees the folder's content. Idempotent: any prior data in the
|
|
49
|
+
* IDB store gets overwritten when paths collide.
|
|
50
|
+
*/
|
|
51
|
+
export declare function copyFolderToIdb(handle: FileSystemDirectoryHandle, connectionId: string): Promise<{
|
|
52
|
+
copied: number;
|
|
53
|
+
failed: {
|
|
54
|
+
path: string;
|
|
55
|
+
reason: string;
|
|
56
|
+
}[];
|
|
57
|
+
}>;
|
|
58
|
+
export declare function hasAnyFile(entries: FileEntry[]): boolean;
|
|
59
|
+
export { readFileSync, statSync };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ProfileVFS } from './ProfileVFS';
|
|
2
|
+
/**
|
|
3
|
+
* Rewrite profile-local asset references in Lua-supplied HTML to the
|
|
4
|
+
* `/__vfs/<connectionId>/<path>` URLs the service worker serves.
|
|
5
|
+
*
|
|
6
|
+
* Mudlet renders `echo(labelName, html)` as Qt rich text, where
|
|
7
|
+
* `<img src="/home/user/.config/mudlet/profiles/X/pkg/icon.png">` loads straight
|
|
8
|
+
* off the local filesystem. In the browser there is no such filesystem — the
|
|
9
|
+
* bytes live in the profile's ProfileVFS, reachable only through the service
|
|
10
|
+
* worker — so those paths have to be rebased or the images silently 404 (on a
|
|
11
|
+
* dev server they resolve to the SPA fallback `index.html`, which decodes as a
|
|
12
|
+
* broken image).
|
|
13
|
+
*
|
|
14
|
+
* Two kinds of reference are rewritten:
|
|
15
|
+
* - `src` attributes (`<img>`, and anything else Qt resolves as a resource)
|
|
16
|
+
* - `url(...)` refs inside an inline `style` attribute, via the same
|
|
17
|
+
* stylesheet rewriter used for setLabelStyleSheet
|
|
18
|
+
*
|
|
19
|
+
* `href` is deliberately left alone: label links are navigation targets
|
|
20
|
+
* (openUrl / setLinkStyle), not embedded resources, and rewriting them would
|
|
21
|
+
* turn an anchor into a VFS fetch.
|
|
22
|
+
*
|
|
23
|
+
* Absolute http(s)/data:/blob:/already-`__vfs` references pass through
|
|
24
|
+
* untouched, as do paths when no VFS is mounted.
|
|
25
|
+
*/
|
|
26
|
+
export declare function rewriteVfsUrlsInHtml(html: string, connectionId: string, vfs: ProfileVFS): string;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ProfileVFS } from './ProfileVFS';
|
|
2
|
+
export declare function vfsUrlPrefix(): string;
|
|
3
|
+
/** Register a mounted profile so the service worker can read its files. */
|
|
4
|
+
export declare function registerVfs(connectionId: string, vfs: ProfileVFS): void;
|
|
5
|
+
/** Drop the mapping and clear cached responses for this connection. */
|
|
6
|
+
export declare function unregisterVfs(connectionId: string): void;
|
|
7
|
+
/** Tell the SW to drop one cached file (call after writes). */
|
|
8
|
+
export declare function invalidateVfsPath(connectionId: string, path: string): void;
|
|
9
|
+
/** Build a URL the SW will resolve to bytes from `vfs.readBinaryFile(path)`. */
|
|
10
|
+
export declare function vfsUrlFor(connectionId: string, path: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Register the service worker and wait until it controls this page. Safe to
|
|
13
|
+
* call multiple times; resolves to false if the browser doesn't support SWs
|
|
14
|
+
* or registration failed.
|
|
15
|
+
*/
|
|
16
|
+
export declare function registerVfsServiceWorker(): Promise<boolean>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal Cloudflare API client for the proxy-deploy wizard.
|
|
3
|
+
*
|
|
4
|
+
* The wizard uses the user's API token to:
|
|
5
|
+
* 1. List accounts the token has access to (verifyToken / listAccounts)
|
|
6
|
+
* 2. Upload the proxy worker script (deployWorker)
|
|
7
|
+
* 3. Enable the *.workers.dev route on it (enableWorkersDevRoute)
|
|
8
|
+
* 4. Look up the account's workers.dev subdomain (getWorkersSubdomain)
|
|
9
|
+
*
|
|
10
|
+
* Cloudflare's API rejects cross-origin browser requests, so every call is
|
|
11
|
+
* tunneled through a relay Worker's HTTP-forward mode (`?url=<target>`). The
|
|
12
|
+
* relay adds CORS headers and strips Origin/Referer/Cookie before forwarding;
|
|
13
|
+
* the Authorization header is preserved.
|
|
14
|
+
*
|
|
15
|
+
* The token never leaves component state — it's consumed once per deploy and
|
|
16
|
+
* never persisted.
|
|
17
|
+
*/
|
|
18
|
+
export interface CloudflareAccount {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
}
|
|
22
|
+
export declare class CloudflareApiError extends Error {
|
|
23
|
+
readonly status: number;
|
|
24
|
+
readonly cfErrors?: {
|
|
25
|
+
code: number;
|
|
26
|
+
message: string;
|
|
27
|
+
}[];
|
|
28
|
+
constructor(message: string, status: number, cfErrors?: {
|
|
29
|
+
code: number;
|
|
30
|
+
message: string;
|
|
31
|
+
}[]);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Lists accounts visible to the token. Doubles as a token-validity check:
|
|
35
|
+
* an invalid token returns a Cloudflare error envelope which we surface.
|
|
36
|
+
*/
|
|
37
|
+
export declare function listAccounts(token: string, proxyBase?: string): Promise<CloudflareAccount[]>;
|
|
38
|
+
/**
|
|
39
|
+
* Uploads a Worker script via the multipart "modules" format. The script is
|
|
40
|
+
* sent as an ES module so `import { connect } from 'cloudflare:sockets'` works.
|
|
41
|
+
*/
|
|
42
|
+
export declare function deployWorker(token: string, accountId: string, scriptName: string, scriptSource: string, proxyBase?: string): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Enables (or disables) the auto-assigned *.workers.dev route for a script.
|
|
45
|
+
* Without this the script is uploaded but not reachable.
|
|
46
|
+
*/
|
|
47
|
+
export declare function enableWorkersDevRoute(token: string, accountId: string, scriptName: string, proxyBase?: string): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Returns the account's workers.dev subdomain (e.g. "yourname" → "*.yourname.workers.dev").
|
|
50
|
+
* If the user has never created one, the API returns an empty string and the
|
|
51
|
+
* wizard surfaces a friendlier error.
|
|
52
|
+
*/
|
|
53
|
+
export declare function getWorkersSubdomain(token: string, accountId: string, proxyBase?: string): Promise<string>;
|
|
54
|
+
export declare function buildWorkerWssUrl(scriptName: string, subdomain: string): string;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { type AppSchema, type MudConnection, type AliasNode, type ButtonNode, type KeyNode, type TimerNode, type TriggerNode, type ScriptNode, type ScriptEditorBounds, type ModalBounds, type ClientSettings, type ProfileSettings, type PackageManifest, type WindowLayoutSnapshot, type ProfileVariables } from './schema';
|
|
2
|
+
import type { MudletVariable } from '../import/mudletVariables';
|
|
3
|
+
import type { MudletImportResult } from '../import/mudletXmlImport';
|
|
4
|
+
import type { WindowOpenOptions } from '../ui/windows/types';
|
|
5
|
+
interface AppStore extends AppSchema {
|
|
6
|
+
/** Adds a connection and returns its newly generated id (so callers can
|
|
7
|
+
* immediately attach per-profile data like saved login credentials). */
|
|
8
|
+
addConnection: (data: Omit<MudConnection, 'id'>) => string;
|
|
9
|
+
updateConnection: (id: string, data: Omit<MudConnection, 'id'>) => void;
|
|
10
|
+
/** Partial update preserving fields the patch doesn't mention. Used for
|
|
11
|
+
* surgical edits (icon, login creds) that must not wipe the rest of the
|
|
12
|
+
* connection record. Keys set to `undefined` are removed. */
|
|
13
|
+
patchConnection: (id: string, patch: Partial<Omit<MudConnection, 'id'>>) => void;
|
|
14
|
+
removeConnection: (id: string) => void;
|
|
15
|
+
/** Reorder the profile list to match `orderedIds`. Ids not present in the
|
|
16
|
+
* list are ignored; any existing connection missing from `orderedIds` is
|
|
17
|
+
* appended in its current relative order (so a stale list can't drop
|
|
18
|
+
* profiles). Backs drag-to-rearrange on the connection screen. */
|
|
19
|
+
reorderConnections: (orderedIds: string[]) => void;
|
|
20
|
+
patchClient: (patch: Partial<ClientSettings>) => void;
|
|
21
|
+
patchConnectionProfile: (connectionId: string, patch: Partial<ProfileSettings>) => void;
|
|
22
|
+
saveWindowHint: (connectionId: string, panelId: string, hint: WindowOpenOptions) => void;
|
|
23
|
+
clearWindowHints: (connectionId: string) => void;
|
|
24
|
+
saveDockExtents: (connectionId: string, extents: Record<string, number>) => void;
|
|
25
|
+
saveLayoutSnapshot: (connectionId: string, snapshot: WindowLayoutSnapshot) => void;
|
|
26
|
+
/** Replace the set of global names flagged to persist (Mudlet save-list).
|
|
27
|
+
* Edited from the Variables view; triggers a profile-data save. */
|
|
28
|
+
setVariableSaveList: (connectionId: string, saveList: string[]) => void;
|
|
29
|
+
/** Replace the captured variable values without disturbing the save-list
|
|
30
|
+
* reference — so the engine can refresh them on save without re-triggering
|
|
31
|
+
* the save subscription (which keys on the save-list, not values). */
|
|
32
|
+
setVariableValues: (connectionId: string, values: MudletVariable[]) => void;
|
|
33
|
+
addScript: (connectionId: string, data: Omit<ScriptNode, 'id'>) => string;
|
|
34
|
+
updateScript: (connectionId: string, id: string, patch: Partial<Omit<ScriptNode, 'id'>>) => void;
|
|
35
|
+
removeScript: (connectionId: string, id: string) => void;
|
|
36
|
+
addAlias: (connectionId: string, data: Omit<AliasNode, 'id'>) => string;
|
|
37
|
+
updateAlias: (connectionId: string, id: string, patch: Partial<Omit<AliasNode, 'id'>>) => void;
|
|
38
|
+
updateAliases: (connectionId: string, patches: ReadonlyArray<{
|
|
39
|
+
id: string;
|
|
40
|
+
patch: Partial<Omit<AliasNode, 'id'>>;
|
|
41
|
+
}>) => void;
|
|
42
|
+
removeAlias: (connectionId: string, id: string) => void;
|
|
43
|
+
addTrigger: (connectionId: string, data: Omit<TriggerNode, 'id'>) => string;
|
|
44
|
+
updateTrigger: (connectionId: string, id: string, patch: Partial<Omit<TriggerNode, 'id'>>) => void;
|
|
45
|
+
/** Bulk apply enabled/disabled (or any partial) to many triggers in one set(). */
|
|
46
|
+
updateTriggers: (connectionId: string, patches: ReadonlyArray<{
|
|
47
|
+
id: string;
|
|
48
|
+
patch: Partial<Omit<TriggerNode, 'id'>>;
|
|
49
|
+
}>) => void;
|
|
50
|
+
removeTrigger: (connectionId: string, id: string) => void;
|
|
51
|
+
removeTriggers: (connectionId: string, ids: ReadonlyArray<string>) => void;
|
|
52
|
+
addTimer: (connectionId: string, data: Omit<TimerNode, 'id'>) => string;
|
|
53
|
+
updateTimer: (connectionId: string, id: string, patch: Partial<Omit<TimerNode, 'id'>>) => void;
|
|
54
|
+
updateTimers: (connectionId: string, patches: ReadonlyArray<{
|
|
55
|
+
id: string;
|
|
56
|
+
patch: Partial<Omit<TimerNode, 'id'>>;
|
|
57
|
+
}>) => void;
|
|
58
|
+
removeTimer: (connectionId: string, id: string) => void;
|
|
59
|
+
removeTimers: (connectionId: string, ids: ReadonlyArray<string>) => void;
|
|
60
|
+
removeAliases: (connectionId: string, ids: ReadonlyArray<string>) => void;
|
|
61
|
+
addKeybinding: (connectionId: string, data: Omit<KeyNode, 'id'>) => string;
|
|
62
|
+
updateKeybinding: (connectionId: string, id: string, patch: Partial<Omit<KeyNode, 'id'>>) => void;
|
|
63
|
+
removeKeybinding: (connectionId: string, id: string) => void;
|
|
64
|
+
removeKeybindings: (connectionId: string, ids: ReadonlyArray<string>) => void;
|
|
65
|
+
addButton: (connectionId: string, data: Omit<ButtonNode, 'id'>) => string;
|
|
66
|
+
updateButton: (connectionId: string, id: string, patch: Partial<Omit<ButtonNode, 'id'>>) => void;
|
|
67
|
+
removeButton: (connectionId: string, id: string) => void;
|
|
68
|
+
moveScript: (connectionId: string, id: string, newParentId: string | null, insertBeforeId: string | null) => void;
|
|
69
|
+
moveAlias: (connectionId: string, id: string, newParentId: string | null, insertBeforeId: string | null) => void;
|
|
70
|
+
moveTrigger: (connectionId: string, id: string, newParentId: string | null, insertBeforeId: string | null) => void;
|
|
71
|
+
moveTimer: (connectionId: string, id: string, newParentId: string | null, insertBeforeId: string | null) => void;
|
|
72
|
+
moveKeybinding: (connectionId: string, id: string, newParentId: string | null, insertBeforeId: string | null) => void;
|
|
73
|
+
moveButton: (connectionId: string, id: string, newParentId: string | null, insertBeforeId: string | null) => void;
|
|
74
|
+
saveScriptEditorBounds: (connectionId: string, bounds: ScriptEditorBounds) => void;
|
|
75
|
+
saveModalBounds: (connectionId: string, key: string, bounds: ModalBounds) => void;
|
|
76
|
+
installPackage: (connectionId: string, manifest: PackageManifest, data: MudletImportResult) => void;
|
|
77
|
+
uninstallPackage: (connectionId: string, packageName: string) => void;
|
|
78
|
+
updatePackageManifest: (connectionId: string, packageName: string, patch: Partial<Omit<PackageManifest, 'name'>>) => void;
|
|
79
|
+
/** Replace the VFS-persisted automation slices for one connection in a single
|
|
80
|
+
* set(). Called once on profile open, after its VFS mounts, to seed the
|
|
81
|
+
* store from `.mudix/profile.json`. Missing keys reset to empty arrays. */
|
|
82
|
+
hydrateConnectionData: (connectionId: string, data: PersistedConnectionData) => void;
|
|
83
|
+
}
|
|
84
|
+
/** The per-connection slices persisted in the profile VFS (see profileVfsData.ts). */
|
|
85
|
+
interface PersistedConnectionData {
|
|
86
|
+
scripts?: ScriptNode[];
|
|
87
|
+
aliases?: AliasNode[];
|
|
88
|
+
triggers?: TriggerNode[];
|
|
89
|
+
timers?: TimerNode[];
|
|
90
|
+
keybindings?: KeyNode[];
|
|
91
|
+
buttons?: ButtonNode[];
|
|
92
|
+
packages?: PackageManifest[];
|
|
93
|
+
profile?: Partial<ProfileSettings>;
|
|
94
|
+
windowHints?: Record<string, WindowOpenOptions>;
|
|
95
|
+
dockExtents?: Record<string, number>;
|
|
96
|
+
scriptEditorBounds?: ScriptEditorBounds;
|
|
97
|
+
modalBounds?: Record<string, ModalBounds>;
|
|
98
|
+
layoutSnapshot?: WindowLayoutSnapshot;
|
|
99
|
+
variables?: ProfileVariables;
|
|
100
|
+
}
|
|
101
|
+
/** localStorage key + schema version for the persisted store. Exported so the
|
|
102
|
+
* cross-tab sync (crossTabSync.ts) can match `storage` events to this store and
|
|
103
|
+
* reject writes from a different schema version. */
|
|
104
|
+
export declare const MUDIX_STORE_NAME = "mudix_v1";
|
|
105
|
+
export declare const MUDIX_STORE_VERSION = 21;
|
|
106
|
+
/** One-time localStorage key holding pre-v21 per-profile UI/layout/settings
|
|
107
|
+
* slices, stashed by the v21 migration so they can be moved into each profile's
|
|
108
|
+
* VFS (.mudix/profile.json) the first time it's opened. Kept separate from the
|
|
109
|
+
* persisted store blob so editing the connections list (which rewrites the
|
|
110
|
+
* blob) can't drop un-migrated profiles' data. Consumed per-profile by
|
|
111
|
+
* loadProfileData, then removed when empty. */
|
|
112
|
+
export declare const MIGRATION_BACKUP_KEY = "mudix_profile_migration_v21";
|
|
113
|
+
export declare const useAppStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<AppStore>, "setState" | "persist"> & {
|
|
114
|
+
setState(partial: AppStore | Partial<AppStore> | ((state: AppStore) => AppStore | Partial<AppStore>), replace?: false | undefined): unknown;
|
|
115
|
+
setState(state: AppStore | ((state: AppStore) => AppStore), replace: true): unknown;
|
|
116
|
+
persist: {
|
|
117
|
+
setOptions: (options: Partial<import("zustand/middleware").PersistOptions<AppStore, {
|
|
118
|
+
connections: MudConnection[];
|
|
119
|
+
client: ClientSettings;
|
|
120
|
+
}, unknown>>) => void;
|
|
121
|
+
clearStorage: () => void;
|
|
122
|
+
rehydrate: () => Promise<void> | void;
|
|
123
|
+
hasHydrated: () => boolean;
|
|
124
|
+
onHydrate: (fn: (state: AppStore) => void) => () => void;
|
|
125
|
+
onFinishHydration: (fn: (state: AppStore) => void) => () => void;
|
|
126
|
+
getOptions: () => Partial<import("zustand/middleware").PersistOptions<AppStore, {
|
|
127
|
+
connections: MudConnection[];
|
|
128
|
+
client: ClientSettings;
|
|
129
|
+
}, unknown>>;
|
|
130
|
+
};
|
|
131
|
+
}>;
|
|
132
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PersistStorage } from 'zustand/middleware';
|
|
2
|
+
/**
|
|
3
|
+
* Zustand PersistStorage adapter that coalesces rapid mutations into a single
|
|
4
|
+
* write — *including* the JSON serialization step.
|
|
5
|
+
*
|
|
6
|
+
* Using `createJSONStorage` over a debounced Web-Storage wrapper only collapses
|
|
7
|
+
* the localStorage.setItem call; zustand still runs `JSON.stringify(state)`
|
|
8
|
+
* before each setItem, so N mutations cost N full serializations of the
|
|
9
|
+
* persisted blob (scripts, triggers, packages, …). Implementing PersistStorage
|
|
10
|
+
* directly lets us hold the unserialized object and stringify exactly once,
|
|
11
|
+
* at flush time.
|
|
12
|
+
*
|
|
13
|
+
* The latest pending value is flushed synchronously on `pagehide`,
|
|
14
|
+
* `visibilitychange→hidden`, and `beforeunload` so a tab close right after a
|
|
15
|
+
* mutation doesn't lose state. `getItem` honours an in-flight pending value so
|
|
16
|
+
* the adapter is internally consistent even mid-debounce.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createDebouncedJsonStorage<S>(delayMs: number): PersistStorage<S>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ClientSettings, type ProfileSettings, type Theme } from './schema';
|
|
2
|
+
/**
|
|
3
|
+
* Active profile id, provided by ProfileSession. `null` outside a profile
|
|
4
|
+
* (e.g. on the connection screen) — settings consumers fall through to
|
|
5
|
+
* PROFILE_DEFAULTS in that case.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ConnectionIdContext: import("react").Context<string | null>;
|
|
8
|
+
export declare function useConnectionId(): string | null;
|
|
9
|
+
/** Read one ProfileSettings field for the active profile (from context). */
|
|
10
|
+
export declare function useProfileField<K extends keyof ProfileSettings>(key: K): ProfileSettings[K];
|
|
11
|
+
/** Read one ClientSettings field. */
|
|
12
|
+
export declare function useClientField<K extends keyof ClientSettings>(key: K): ClientSettings[K];
|
|
13
|
+
/** The theme actually in effect: the active profile's override if it has one,
|
|
14
|
+
* else the launcher theme. Use anywhere a profile-scoped component needs the
|
|
15
|
+
* current theme (e.g. CodeMirror editors). Outside a profile (no context) it
|
|
16
|
+
* resolves to the launcher theme. */
|
|
17
|
+
export declare function useEffectiveTheme(): Theme;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { type AppSchema, type MudConnection, type ConnectionMode, type ClientSettings, type ProfileSettings, type MapperSettings, type MapInfoBgColor, type ProtocolSettings, type BooleanProtocolKey, type Theme, type OutputFontSource, APP_DEFAULTS, PROFILE_DEFAULTS, MAPPER_DEFAULTS, MAP_INFO_BG_DEFAULT, PROTOCOL_DEFAULTS, WS_SUBPROTOCOL_CHOICES, DEFAULT_PROXY_URL, connectionUrl, connectionDisplayAddr, connectionSecureTransport, selectProfileField } from './schema';
|
|
2
|
+
export { useAppStore } from './appStore';
|
|
3
|
+
export { initCrossTabSync } from './crossTabSync';
|
|
4
|
+
export { ConnectionIdContext, useConnectionId, useProfileField, useClientField, useEffectiveTheme } from './hooks';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type LogEntry, type LogSession } from './logStorage';
|
|
2
|
+
/** `YYYY-MM-DD HH-MM-SS`, safe for filenames. */
|
|
3
|
+
export declare function formatSessionFileStamp(ts: number): string;
|
|
4
|
+
/** `HH:MM:SS` for per-line timestamps. */
|
|
5
|
+
export declare function formatTime(ts: number): string;
|
|
6
|
+
/** `YYYY-MM-DD HH:MM:SS` for session labels. */
|
|
7
|
+
export declare function formatDateTime(ts: number): string;
|
|
8
|
+
/** A standalone, self-contained HTML document for one session. */
|
|
9
|
+
export declare function buildSessionHtml(session: LogSession, entries: LogEntry[]): string;
|
|
10
|
+
/** Trigger a browser download for an in-memory blob. */
|
|
11
|
+
export declare function downloadBlob(filename: string, blob: Blob): void;
|
|
12
|
+
/** Download one session as a standalone `.html` file. */
|
|
13
|
+
export declare function exportSessionHtml(session: LogSession): Promise<void>;
|
|
14
|
+
/** Bundle several sessions into one `.zip`, one HTML file per session. */
|
|
15
|
+
export declare function exportSessionsZip(sessions: LogSession[]): Promise<void>;
|
|
16
|
+
/** Shape of the JSON export/import payload. */
|
|
17
|
+
export interface LogExportJson {
|
|
18
|
+
version: 1;
|
|
19
|
+
exportedAt: number;
|
|
20
|
+
sessions: Array<{
|
|
21
|
+
session: LogSession;
|
|
22
|
+
entries: LogEntry[];
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
/** Export sessions (with their entries) to a `.json` file. */
|
|
26
|
+
export declare function exportSessionsJson(sessions: LogSession[]): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Import a previously exported JSON payload. Each session is re-keyed with a
|
|
29
|
+
* fresh id so re-importing never clobbers an existing session, and entry rows
|
|
30
|
+
* drop their old auto-increment ids. Returns the number of sessions imported.
|
|
31
|
+
*/
|
|
32
|
+
export declare function importSessionsJson(text: string): Promise<number>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** One recorded gameplay session (a single profile open). */
|
|
2
|
+
export interface LogSession {
|
|
3
|
+
/** UUID; also the foreign key on every {@link LogEntry}. */
|
|
4
|
+
id: string;
|
|
5
|
+
connectionId: string;
|
|
6
|
+
/** Display name captured at record time, so the browser can label the
|
|
7
|
+
* session even after the connection is renamed or deleted. */
|
|
8
|
+
connectionName: string;
|
|
9
|
+
startedAt: number;
|
|
10
|
+
/** Updated on every flush; the wall-clock time of the last logged line. */
|
|
11
|
+
endedAt: number;
|
|
12
|
+
entryCount: number;
|
|
13
|
+
}
|
|
14
|
+
/** One captured output line. `html` is the styled, HTML-escaped render
|
|
15
|
+
* (snapshotted at emit time); `plain` is the unstyled text used for search. */
|
|
16
|
+
export interface LogEntry {
|
|
17
|
+
/** Auto-increment key, assigned by IndexedDB on insert. */
|
|
18
|
+
id?: number;
|
|
19
|
+
sessionId: string;
|
|
20
|
+
/** Monotonic ordering within the session (guards against equal timestamps). */
|
|
21
|
+
seq: number;
|
|
22
|
+
timestamp: number;
|
|
23
|
+
/** Mirrors the `message` event type: 'mud' | 'echo' | 'script' | 'info' | … */
|
|
24
|
+
type: string;
|
|
25
|
+
html: string;
|
|
26
|
+
plain: string;
|
|
27
|
+
}
|
|
28
|
+
/** Insert a session record (call once, on the first flush that has entries). */
|
|
29
|
+
export declare function createSession(session: LogSession): Promise<void>;
|
|
30
|
+
/** Merge a partial update into an existing session record (endedAt/entryCount). */
|
|
31
|
+
export declare function updateSession(id: string, patch: Partial<LogSession>): Promise<void>;
|
|
32
|
+
/** Append a batch of entries in a single transaction. */
|
|
33
|
+
export declare function appendEntries(entries: LogEntry[]): Promise<void>;
|
|
34
|
+
/** All sessions, newest first. Optionally filtered to one connection. */
|
|
35
|
+
export declare function listSessions(connectionId?: string): Promise<LogSession[]>;
|
|
36
|
+
/** All entries for a session, in capture order. */
|
|
37
|
+
export declare function getSessionEntries(sessionId: string): Promise<LogEntry[]>;
|
|
38
|
+
/** Delete a session and every entry that belongs to it. */
|
|
39
|
+
export declare function deleteSession(id: string): Promise<void>;
|
|
40
|
+
/** Delete several sessions (and their entries). */
|
|
41
|
+
export declare function deleteSessions(ids: string[]): Promise<void>;
|
|
42
|
+
/** Remove every log for a connection — called when the connection is deleted. */
|
|
43
|
+
export declare function deleteSessionsForConnection(connectionId: string): Promise<void>;
|
|
44
|
+
/** Wipe all recorded logs across every connection. */
|
|
45
|
+
export declare function clearAllLogs(): Promise<void>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ScriptNode, AliasNode, TriggerNode, TimerNode, KeyNode, ButtonNode, PackageManifest, ProfileSettings, ScriptEditorBounds, ModalBounds, WindowLayoutSnapshot, ProfileVariables } from './schema';
|
|
2
|
+
import type { WindowOpenOptions } from '../ui/windows/types';
|
|
3
|
+
import type { ProfileVFS } from '../scripting/vfs/ProfileVFS';
|
|
4
|
+
/**
|
|
5
|
+
* Per-profile data is stored inside that profile's own VFS rather than the
|
|
6
|
+
* shared localStorage blob — see the design notes in CLAUDE.md / the storage
|
|
7
|
+
* layer. One JSON file per profile holds the bulky tree data (scripts, aliases,
|
|
8
|
+
* triggers, …) AND the per-profile UI/settings/layout slices, so the only
|
|
9
|
+
* per-profile state left in localStorage is the connection record itself. That
|
|
10
|
+
* makes each profile single-writer (one tab owns it via the cross-tab lock),
|
|
11
|
+
* eliminating the multi-tab clobber the shared blob suffered.
|
|
12
|
+
*
|
|
13
|
+
* The file is dot-prefixed so it stays out of the way in the user-browsable
|
|
14
|
+
* file area. `ProfileVFS.writeFile` creates the `.mudix/` parent dir for us.
|
|
15
|
+
*/
|
|
16
|
+
export declare const PROFILE_DATA_PATH = ".mudix/profile.json";
|
|
17
|
+
export interface PersistedProfileData {
|
|
18
|
+
version: number;
|
|
19
|
+
scripts: ScriptNode[];
|
|
20
|
+
aliases: AliasNode[];
|
|
21
|
+
triggers: TriggerNode[];
|
|
22
|
+
timers: TimerNode[];
|
|
23
|
+
keybindings: KeyNode[];
|
|
24
|
+
buttons: ButtonNode[];
|
|
25
|
+
packages: PackageManifest[];
|
|
26
|
+
/** Mudlet saved-variables: the save-list + last captured values. Optional so
|
|
27
|
+
* older files (no variables) still parse. */
|
|
28
|
+
variables?: ProfileVariables;
|
|
29
|
+
profile?: Partial<ProfileSettings>;
|
|
30
|
+
windowHints?: Record<string, WindowOpenOptions>;
|
|
31
|
+
dockExtents?: Record<string, number>;
|
|
32
|
+
scriptEditorBounds?: ScriptEditorBounds;
|
|
33
|
+
modalBounds?: Record<string, ModalBounds>;
|
|
34
|
+
layoutSnapshot?: WindowLayoutSnapshot;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Read `.mudix/profile.json` from the profile VFS and push it into the store
|
|
38
|
+
* for `connectionId`. Also completes the one-time v21 migration: if this
|
|
39
|
+
* profile's UI/settings/layout slices haven't moved into the VFS yet, they're
|
|
40
|
+
* pulled from the migration backup, hydrated, written to the VFS, and dropped
|
|
41
|
+
* from the backup. No-op for a fresh profile with nothing to load.
|
|
42
|
+
*/
|
|
43
|
+
export declare function loadProfileData(vfs: ProfileVFS, connectionId: string): void;
|
|
44
|
+
/** Serialize a profile's automation + UI slices for `connectionId` from the store. */
|
|
45
|
+
export declare function serializeProfileData(connectionId: string): string;
|
|
46
|
+
/** Write the current store state for `connectionId` to the profile VFS. */
|
|
47
|
+
export declare function saveProfileData(vfs: ProfileVFS, connectionId: string): void;
|