overmux 0.0.8 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/bin.js +58 -20
  3. package/dist/bin.js.map +1 -1
  4. package/dist/docs/100-introduction/300-why-i-built-overmux.md +1 -1
  5. package/dist/docs/200-getting-started/200-install-overmux-desktop.md +13 -0
  6. package/dist/docs/400-reference/500-server/100-resources.md +25 -0
  7. package/dist/docs/400-reference/500-server/500-api.md +4 -2
  8. package/dist/docs/400-reference/600-client/010-commands.md +0 -29
  9. package/dist/exports/client.d.ts +1 -1
  10. package/dist/exports/client.d.ts.map +1 -1
  11. package/dist/exports/client.js +89 -25
  12. package/dist/exports/client.js.map +1 -1
  13. package/dist/exports/{index-Cz3xkCa4.d.ts → index-Dk11nKIv.d.ts} +2 -2
  14. package/dist/exports/index-Dk11nKIv.d.ts.map +1 -0
  15. package/dist/exports/index.d.ts +1 -1
  16. package/dist/exports/index.js.map +1 -1
  17. package/dist/internal/server/coordinator/server-child.js +75 -22
  18. package/dist/internal/server/coordinator/server-child.js.map +1 -1
  19. package/docs/100-introduction/300-why-i-built-overmux.md +1 -1
  20. package/docs/200-getting-started/200-install-overmux-desktop.md +13 -0
  21. package/docs/400-reference/500-server/100-resources.md +25 -0
  22. package/docs/400-reference/500-server/500-api.md +4 -2
  23. package/docs/400-reference/600-client/010-commands.md +0 -29
  24. package/package.json +1 -1
  25. package/src/internal/client/overmux-react.ts +121 -27
  26. package/src/internal/server/runtime/runtime-resources.ts +99 -20
  27. package/src/internal/server/websocket-connection.ts +27 -2
  28. package/src/public/config.ts +1 -1
  29. package/dist/exports/index-Cz3xkCa4.d.ts.map +0 -1
@@ -19,4 +19,4 @@ I lived in a customized tmux setup. But kept noticing that that the terminal, fo
19
19
 
20
20
  [Herdr](https://github.com/herdrdev/herdr) (a TUI) and [Orca](https://github.com/stablyai/orca) (web based) offer a decent default experience. But they lack the customizability I love with the terminal and neovim. They use their own muxer implementations and dictate workflows.
21
21
 
22
- This future filled me with existential dread, so I built Overmux to embed my terminal in a Desktop webapp and build my own experience with a mix of tmux terminals + custom web uis.
22
+ This future didn't _spark joy_ for me, so I built Overmux to embed my terminal in a Desktop webapp and build my own experience with a mix of tmux terminals + custom web uis.
@@ -22,6 +22,19 @@ Download the ZIP for your Mac from the [Overmux releases](https://github.com/ric
22
22
 
23
23
  Overmux is not currently signed or notarized. Follow [Apple's instructions for opening an app from an unidentified developer](https://support.apple.com/en-us/102445) to allow it to run.
24
24
 
25
+ <details>
26
+ <summary>macOS says Overmux is damaged or the developer cannot be verified</summary>
27
+
28
+ For quarantine-related blocking, run this **only for a trusted download from [official Overmux releases](https://github.com/richardgill/overmux/releases)**:
29
+
30
+ ```bash
31
+ xattr -dr com.apple.quarantine "$HOME/Applications/Overmux.app"
32
+ ```
33
+
34
+ Use `/Applications/Overmux.app` instead if you installed it there. Then reopen Overmux in Finder.
35
+
36
+ </details>
37
+
25
38
  ## Linux
26
39
 
27
40
  Download the AppImage or Debian package from the [Overmux releases](https://github.com/richardgill/overmux/releases).
@@ -73,6 +73,31 @@ When the subscription ends, Overmux calls the cleanup function returned by `subs
73
73
 
74
74
  The React code stays the same: `useResource({ id: "ls" })`.
75
75
 
76
+ ### Asynchronous setup
77
+
78
+ `subscribe` can be synchronous or asynchronous. Both forms return a cleanup function. For example, replace the `ls` resource's `subscribe` handler to resolve the directory's canonical path before watching it:
79
+
80
+ ```ts
81
+ import { watch } from "node:fs";
82
+ import { realpath } from "node:fs/promises";
83
+
84
+ // Inside the resource definition:
85
+ subscribe: async (_input, invalidate, context) => {
86
+ const directory = await realpath("/");
87
+ // The subscription may have ended while resolving the path.
88
+ context.signal.throwIfAborted();
89
+
90
+ const watcher = watch(directory, { signal: context.signal }, () => {
91
+ invalidate();
92
+ });
93
+ return () => watcher.close();
94
+ },
95
+ ```
96
+
97
+ `context.signal` is an `AbortSignal` that Overmux aborts when the client unsubscribes, disconnects, or the server shuts down. Cancellation does not automatically stop an async function: pass the signal to APIs that support it and check it after awaiting setup. Here, `realpath` does not accept a signal, so `throwIfAborted()` prevents starting a watcher if cancellation happened during that work.
98
+
99
+ Overmux calls the returned cleanup function once, even if setup finishes after cancellation. Cleanup may also be asynchronous. In this example, the signal can close the watcher before Overmux calls cleanup; `watcher.close()` is safe to call again. If setup throws before returning cleanup, your handler must release any resources it already acquired.
100
+
76
101
  ## Derived
77
102
 
78
103
  Derived resources compute a value from other resources.
@@ -47,7 +47,7 @@ A resource definition has a `contract` created with `defineResourceContract({ in
47
47
  | Kind | Required handler API |
48
48
  | --- | --- |
49
49
  | `query` | `read(input, context) => output \| Promise<output>` |
50
- | `subscription` | `read(input, context)` and `subscribe(input, invalidate, context) => disposer` |
50
+ | `subscription` | `read(input, context)` and `subscribe(input, invalidate, context) => (() => void \| Promise<void>) \| Promise<() => void \| Promise<void>>` |
51
51
  | `derived` | `dependencies` and `combine(dependencies) => output` |
52
52
 
53
53
  ```ts
@@ -69,7 +69,9 @@ const resources = {
69
69
  };
70
70
  ```
71
71
 
72
- `subscribe` must synchronously return a cleanup function. Overmux calls it when that client subscription, or the server runtime, closes. A derived resource reads the resources named by `dependencies`; invalidating a dependency also invalidates its dependants. See [Resources](./100-resources.md) for contracts, derived dependencies, and invalidation.
72
+ `subscribe` returns a cleanup function, directly or asynchronously. Overmux aborts `context.signal` when the subscription ends, including during setup, on client disconnect, or on server shutdown. Overmux calls the returned cleanup function once, even if setup returns it after cancellation. The cleanup function itself may also be asynchronous. If setup throws before returning cleanup, the handler must release any resources it already acquired. See [Asynchronous setup](./100-resources.md#asynchronous-setup) for an example.
73
+
74
+ A derived resource reads the resources named by `dependencies`; invalidating a dependency also invalidates its dependants. See [Resources](./100-resources.md) for contracts, derived dependencies, and invalidation.
73
75
 
74
76
  ## Stream handlers
75
77
 
@@ -158,32 +158,3 @@ const CommandMenu = () => {
158
158
  Each entry exposes `id`, `title`, `bindings`, `enabled`, and `execute()`. The list includes disabled commands but excludes commands without a registration.
159
159
 
160
160
  Each command appears once, even if multiple components register it. `execute()` selects the handler using the current focus and runs it only if enabled.
161
-
162
- ## Using commands from packages
163
-
164
- Packages can export commands to include alongside your own:
165
-
166
- ```tsx
167
- import { sourceControlCommands } from "@overmux/git/react";
168
-
169
- export const client = defineOvermuxClient({
170
- commands: {
171
- ...commands,
172
- ...sourceControlCommands,
173
- },
174
- component: App,
175
- });
176
- ```
177
-
178
- Adding commands to the registry does not register their handlers. For this package, pass the commands to `SourceControlView`:
179
-
180
- ```tsx
181
- <SourceControlView
182
- {...sourceControlProps}
183
- commandHandles={sourceControlCommands}
184
- />
185
- ```
186
-
187
- The view registers handlers for navigating changed files and scrolling diffs. They then appear in `useCommands()` alongside your own registered commands.
188
-
189
- Keep command IDs unique when combining registries, and pass the same command objects to the client and the component.
@@ -1,4 +1,4 @@
1
- import { B as InstanceIdentity, w as ContractInputArguments } from "./index-Cz3xkCa4.js";
1
+ import { B as InstanceIdentity, w as ContractInputArguments } from "./index-Dk11nKIv.js";
2
2
  import { z } from "zod";
3
3
  import { UseMutationResult } from "@tanstack/react-query";
4
4
  import { CSSProperties, ComponentType, ReactNode, RefObject } from "react";
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","names":[],"sources":["../../src/internal/client/background-notifications.ts","../../src/internal/client/host/desktop-host.ts","../../src/internal/client/clipboard.ts","../../src/internal/client/browser-api.ts","../../src/internal/client/theme-scope.tsx","../../src/internal/client/client-definition.ts","../../src/internal/client/commands.tsx","../../src/internal/client/overmux-react.ts","../../src/internal/client/host/overmux-host.tsx","../../src/internal/client/shortcuts.tsx"],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","names":[],"sources":["../../src/internal/client/background-notifications.ts","../../src/internal/client/host/desktop-host.ts","../../src/internal/client/clipboard.ts","../../src/internal/client/browser-api.ts","../../src/internal/client/theme-scope.tsx","../../src/internal/client/client-definition.ts","../../src/internal/client/commands.tsx","../../src/internal/client/overmux-react.ts","../../src/internal/client/host/overmux-host.tsx","../../src/internal/client/shortcuts.tsx"],"mappings":"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"}
@@ -452,9 +452,95 @@ const useCanonicalInput = (input) => {
452
452
  const key = inputKey(input);
453
453
  return useMemo(() => key ? JSON.parse(key) : void 0, [key]);
454
454
  };
455
- const useResourceById = (id, input, skipped) => {
455
+ const pendingResourceInvalidations = /* @__PURE__ */ new WeakSet();
456
+ const invalidateResource = ({ queryClient, queryKey }) => {
457
+ const query = queryClient.getQueryCache().find({
458
+ exact: true,
459
+ queryKey
460
+ });
461
+ if (query && query.state.fetchStatus !== "idle") {
462
+ pendingResourceInvalidations.add(query);
463
+ return;
464
+ }
465
+ if (query) pendingResourceInvalidations.delete(query);
466
+ queryClient.invalidateQueries({
467
+ exact: true,
468
+ queryKey
469
+ });
470
+ };
471
+ const flushResourceInvalidation = ({ queryClient, queryKey }) => {
472
+ const query = queryClient.getQueryCache().find({
473
+ exact: true,
474
+ queryKey
475
+ });
476
+ if (!query || query.state.fetchStatus !== "idle") return;
477
+ if (pendingResourceInvalidations.delete(query)) queryClient.invalidateQueries({
478
+ exact: true,
479
+ queryKey
480
+ });
481
+ };
482
+ const useResourceInvalidation = ({ queryKey, skipped }) => {
483
+ const [id, canonicalInput] = queryKey;
456
484
  const { manifest, overmuxServerApi } = useRuntime();
457
485
  const queryClient = useQueryClient();
486
+ const invalidate = useCallback(() => invalidateResource({
487
+ queryClient,
488
+ queryKey
489
+ }), [queryClient, queryKey]);
490
+ useEffect(() => {
491
+ if (skipped) return;
492
+ let active = true;
493
+ const cache = queryClient.getQueryCache();
494
+ const observedQuery = cache.find({
495
+ exact: true,
496
+ queryKey
497
+ });
498
+ const unsubscribe = cache.subscribe((event) => {
499
+ if (event.type === "updated" && event.query === observedQuery && event.query.state.fetchStatus === "idle" && pendingResourceInvalidations.has(event.query)) queueMicrotask(() => {
500
+ if (active) flushResourceInvalidation({
501
+ queryClient,
502
+ queryKey
503
+ });
504
+ });
505
+ });
506
+ flushResourceInvalidation({
507
+ queryClient,
508
+ queryKey
509
+ });
510
+ return () => {
511
+ active = false;
512
+ unsubscribe();
513
+ };
514
+ }, [
515
+ queryClient,
516
+ queryKey,
517
+ skipped
518
+ ]);
519
+ useEffect(() => {
520
+ if (skipped || !manifest.resources.includes(id)) return;
521
+ let active = true;
522
+ const unsubscribe = overmuxServerApi.subscribeResource({
523
+ id,
524
+ input: canonicalInput,
525
+ onError: () => active && invalidate(),
526
+ onInvalidate: () => active && invalidate()
527
+ });
528
+ return () => {
529
+ active = false;
530
+ unsubscribe();
531
+ };
532
+ }, [
533
+ manifest.resources,
534
+ canonicalInput,
535
+ id,
536
+ invalidate,
537
+ overmuxServerApi,
538
+ skipped
539
+ ]);
540
+ return invalidate;
541
+ };
542
+ const useResourceById = (id, input, skipped) => {
543
+ const { overmuxServerApi } = useRuntime();
458
544
  const canonicalInput = useCanonicalInput(input);
459
545
  const queryKey = useMemo(() => [id, canonicalInput], [canonicalInput, id]);
460
546
  const query = useQuery({
@@ -465,32 +551,10 @@ const useResourceById = (id, input, skipped) => {
465
551
  }),
466
552
  queryKey
467
553
  });
468
- useEffect(() => !skipped && manifest.resources.includes(id) ? overmuxServerApi.subscribeResource({
469
- id,
470
- input: canonicalInput,
471
- onError: () => void queryClient.invalidateQueries({
472
- exact: true,
473
- queryKey
474
- }),
475
- onInvalidate: () => void queryClient.invalidateQueries({
476
- exact: true,
477
- queryKey
478
- })
479
- }) : void 0, [
480
- manifest.resources,
481
- canonicalInput,
482
- id,
483
- overmuxServerApi,
484
- queryClient,
554
+ const refetch = useResourceInvalidation({
485
555
  queryKey,
486
556
  skipped
487
- ]);
488
- const refetch = useCallback(() => {
489
- queryClient.invalidateQueries({
490
- exact: true,
491
- queryKey
492
- });
493
- }, [queryClient, queryKey]);
557
+ });
494
558
  if (skipped) return;
495
559
  if (query.status === "pending") return {
496
560
  refetch,