overmux 0.0.4 → 0.0.5
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/CHANGELOG.md +34 -0
- package/README.md +2 -2
- package/dist/bin.js +140 -127
- package/dist/bin.js.map +1 -1
- package/dist/docs/000-index.md +2 -4
- package/dist/docs/100-introduction/200-how-overmux-works.md +126 -2
- package/dist/docs/100-introduction/{300-why-overmux.md → 300-why-i-built-overmux.md} +1 -1
- package/dist/docs/200-getting-started/100-install-and-run-overmux.md +2 -2
- package/dist/docs/200-getting-started/400-secure-with-https/200-tailscale-serve.md +3 -3
- package/dist/docs/200-getting-started/400-secure-with-https/300-cloudflare-tunnel.md +2 -2
- package/dist/docs/200-getting-started/400-secure-with-https/400-self-hosted-reverse-proxy.md +2 -2
- package/dist/docs/400-reference/100-project-structure.md +83 -0
- package/dist/docs/400-reference/200-configuration.md +257 -0
- package/dist/docs/400-reference/300-storage-locations.md +46 -0
- package/dist/docs/400-reference/400-authentication-and-security.md +37 -0
- package/dist/docs/400-reference/500-server/000-index.md +13 -0
- package/dist/docs/400-reference/500-server/100-resources.md +191 -0
- package/dist/docs/400-reference/500-server/200-operations.md +111 -0
- package/dist/docs/400-reference/500-server/300-streams.md +140 -0
- package/dist/docs/400-reference/500-server/400-notifications.md +32 -0
- package/dist/docs/400-reference/500-server/500-api.md +118 -0
- package/dist/docs/400-reference/600-client/000-index.md +9 -0
- package/dist/docs/400-reference/600-client/100-api.md +370 -0
- package/dist/docs/400-reference/600-client/200-theming.md +94 -0
- package/dist/docs/400-reference/600-client/300-tech-stack-recommendations.md +12 -0
- package/dist/docs/400-reference/{400-cli → 700-cli}/050-init.md +2 -4
- package/{docs/400-reference/400-cli → dist/docs/400-reference/700-cli}/100-serve.md +9 -4
- package/{docs/400-reference/400-cli → dist/docs/400-reference/700-cli}/200-auth.md +1 -4
- package/dist/docs/400-reference/{400-cli → 700-cli}/300-call.md +1 -4
- package/dist/docs/400-reference/{400-cli → 700-cli}/350-instance.md +1 -4
- package/dist/docs/400-reference/700-cli/600-docs.md +128 -0
- package/dist/docs/400-reference/{400-cli → 700-cli}/700-desktop.md +1 -3
- package/dist/docs/500-hosted-pages.md +0 -1
- package/dist/exports/client.d.ts +5 -14
- package/dist/exports/client.d.ts.map +1 -1
- package/dist/exports/client.js +141 -46
- package/dist/exports/client.js.map +1 -1
- package/dist/exports/{index-DS70rKzo.d.ts → index-Cz3xkCa4.d.ts} +50 -36
- package/dist/exports/index-Cz3xkCa4.d.ts.map +1 -0
- package/dist/exports/index.d.ts +1 -1
- package/dist/exports/index.js +19 -5
- package/dist/exports/index.js.map +1 -1
- package/dist/exports/{notifications-av0FK0yZ.js → notifications-BFAD3QQl.js} +29 -4
- package/dist/exports/notifications-BFAD3QQl.js.map +1 -0
- package/dist/exports/server.d.ts +1 -44
- package/dist/exports/server.d.ts.map +1 -1
- package/dist/exports/server.js +9 -1061
- package/dist/exports/server.js.map +1 -1
- package/dist/internal/server/coordinator/server-child.js +47 -43
- package/dist/internal/server/coordinator/server-child.js.map +1 -1
- package/docs/000-index.md +2 -4
- package/docs/100-introduction/200-how-overmux-works.md +126 -2
- package/docs/100-introduction/{300-why-overmux.md → 300-why-i-built-overmux.md} +1 -1
- package/docs/200-getting-started/100-install-and-run-overmux.md +2 -2
- package/docs/200-getting-started/400-secure-with-https/200-tailscale-serve.md +3 -3
- package/docs/200-getting-started/400-secure-with-https/300-cloudflare-tunnel.md +2 -2
- package/docs/200-getting-started/400-secure-with-https/400-self-hosted-reverse-proxy.md +2 -2
- package/docs/400-reference/100-project-structure.md +83 -0
- package/docs/400-reference/200-configuration.md +257 -0
- package/docs/400-reference/300-storage-locations.md +46 -0
- package/docs/400-reference/400-authentication-and-security.md +37 -0
- package/docs/400-reference/500-server/000-index.md +13 -0
- package/docs/400-reference/500-server/100-resources.md +191 -0
- package/docs/400-reference/500-server/200-operations.md +111 -0
- package/docs/400-reference/500-server/300-streams.md +140 -0
- package/docs/400-reference/500-server/400-notifications.md +32 -0
- package/docs/400-reference/500-server/500-api.md +118 -0
- package/docs/400-reference/600-client/000-index.md +9 -0
- package/docs/400-reference/600-client/100-api.md +370 -0
- package/docs/400-reference/600-client/200-theming.md +94 -0
- package/docs/400-reference/600-client/300-tech-stack-recommendations.md +12 -0
- package/docs/400-reference/{400-cli → 700-cli}/050-init.md +2 -4
- package/{dist/docs/400-reference/400-cli → docs/400-reference/700-cli}/100-serve.md +9 -4
- package/{dist/docs/400-reference/400-cli → docs/400-reference/700-cli}/200-auth.md +1 -4
- package/docs/400-reference/{400-cli → 700-cli}/300-call.md +1 -4
- package/docs/400-reference/{400-cli → 700-cli}/350-instance.md +1 -4
- package/docs/400-reference/700-cli/600-docs.md +128 -0
- package/docs/400-reference/{400-cli → 700-cli}/700-desktop.md +1 -3
- package/docs/500-hosted-pages.md +0 -1
- package/package.json +3 -2
- package/src/internal/cli/app.ts +3 -5
- package/src/internal/cli/commands/docs-ai-context.ts +33 -0
- package/src/internal/cli/commands/docs.ts +19 -2
- package/src/internal/cli/commands/init-template.ts +1 -1
- package/src/internal/cli/commands/serve.ts +3 -0
- package/src/internal/cli/login.ts +9 -9
- package/src/internal/client/client-definition.ts +6 -8
- package/src/internal/client/host/deep-link-navigation.ts +75 -0
- package/src/internal/client/host/overmux-host.tsx +9 -0
- package/src/internal/client/index.ts +0 -6
- package/src/internal/client/overmux-react.ts +71 -40
- package/src/internal/server/auth/auth-service.ts +2 -2
- package/src/internal/server/auth/instance-control.ts +65 -14
- package/src/internal/server/coordinator/ipc-protocol.ts +0 -1
- package/src/internal/server/runtime/create-runtime.ts +5 -3
- package/src/internal/server/runtime/runtime-instance.ts +5 -4
- package/src/internal/server/runtime/runtime-operations.ts +9 -3
- package/src/internal/server/runtime/runtime-resources.ts +12 -32
- package/src/internal/server/runtime/runtime-streams.ts +5 -6
- package/src/internal/server/server-logger.ts +5 -10
- package/src/internal/server/server-startup-options.ts +5 -10
- package/src/internal/server/start-application-server.ts +4 -7
- package/src/public/ai-context.ts +7 -29
- package/src/public/client.ts +0 -6
- package/src/public/config.ts +156 -31
- package/src/public/server.ts +1 -16
- package/dist/docs/100-introduction/100-what-is-overmux.md +0 -7
- package/dist/docs/300-fundamentals/100-project-structure.md +0 -23
- package/dist/docs/300-fundamentals/200-configuration.md +0 -3
- package/dist/docs/300-fundamentals/300-theming.md +0 -54
- package/dist/docs/300-fundamentals/400-server.md +0 -3
- package/dist/docs/300-fundamentals/500-client.md +0 -3
- package/dist/docs/300-fundamentals/600-operations.md +0 -3
- package/dist/docs/300-fundamentals/700-resources.md +0 -3
- package/dist/docs/300-fundamentals/800-streams.md +0 -3
- package/dist/docs/300-fundamentals/900-authentication-and-security.md +0 -3
- package/dist/docs/400-reference/100-configuration.md +0 -23
- package/dist/docs/400-reference/200-server-api.md +0 -21
- package/dist/docs/400-reference/300-client-api.md +0 -39
- package/dist/docs/400-reference/400-cli/400-check.md +0 -20
- package/dist/docs/400-reference/400-cli/500-ai-context.md +0 -102
- package/dist/docs/400-reference/400-cli/600-docs.md +0 -23
- package/dist/exports/index-DS70rKzo.d.ts.map +0 -1
- package/dist/exports/notifications-av0FK0yZ.js.map +0 -1
- package/docs/100-introduction/100-what-is-overmux.md +0 -7
- package/docs/300-fundamentals/100-project-structure.md +0 -23
- package/docs/300-fundamentals/200-configuration.md +0 -3
- package/docs/300-fundamentals/300-theming.md +0 -54
- package/docs/300-fundamentals/400-server.md +0 -3
- package/docs/300-fundamentals/500-client.md +0 -3
- package/docs/300-fundamentals/600-operations.md +0 -3
- package/docs/300-fundamentals/700-resources.md +0 -3
- package/docs/300-fundamentals/800-streams.md +0 -3
- package/docs/300-fundamentals/900-authentication-and-security.md +0 -3
- package/docs/400-reference/100-configuration.md +0 -23
- package/docs/400-reference/200-server-api.md +0 -21
- package/docs/400-reference/300-client-api.md +0 -39
- package/docs/400-reference/400-cli/400-check.md +0 -20
- package/docs/400-reference/400-cli/500-ai-context.md +0 -102
- package/docs/400-reference/400-cli/600-docs.md +0 -23
- package/src/internal/cli/commands/ai.ts +0 -44
package/src/public/config.ts
CHANGED
|
@@ -11,40 +11,51 @@ export type InstanceContext = {
|
|
|
11
11
|
getDeepLinkPrefix: () => string;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
type ResourceInputMap = Readonly<Record<string, unknown>>;
|
|
15
|
+
|
|
16
|
+
// Keep IDs paired with their raw inputs when checking calls and reusable handlers.
|
|
17
|
+
type InvalidationArguments<TInputs extends ResourceInputMap> = {
|
|
18
|
+
[TId in keyof TInputs & string]: [resourceId: TId, input?: TInputs[TId]];
|
|
19
|
+
}[keyof TInputs & string];
|
|
20
|
+
|
|
21
|
+
export type HandlerContext<TInputs extends ResourceInputMap = {}> = {
|
|
15
22
|
instance: InstanceContext;
|
|
16
|
-
invalidate: (
|
|
23
|
+
invalidate: (...args: InvalidationArguments<TInputs>) => void;
|
|
17
24
|
signal: AbortSignal;
|
|
18
25
|
};
|
|
19
26
|
|
|
20
|
-
export type OperationContext
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
export type OperationContext<TInputs extends ResourceInputMap = {}> =
|
|
28
|
+
HandlerContext<TInputs> & {
|
|
29
|
+
notifications: Notifications;
|
|
30
|
+
};
|
|
23
31
|
|
|
24
32
|
export type OperationDefinition<
|
|
25
33
|
TInput extends z.ZodType = z.ZodType,
|
|
26
34
|
TOutput extends z.ZodType = z.ZodVoid,
|
|
35
|
+
TContext = OperationContext,
|
|
27
36
|
> = {
|
|
28
37
|
handle: (
|
|
29
38
|
input: z.output<TInput>,
|
|
30
|
-
context:
|
|
39
|
+
context: TContext,
|
|
31
40
|
) => Promise<z.input<NoInfer<TOutput>>> | z.input<NoInfer<TOutput>>;
|
|
32
41
|
input: TInput;
|
|
33
42
|
output: TOutput;
|
|
34
43
|
};
|
|
35
44
|
|
|
45
|
+
// Infer schemas from this definition, not a surrounding operation map's broad constraint.
|
|
36
46
|
export const defineOperation = <
|
|
37
47
|
TInput extends z.ZodType,
|
|
38
48
|
TOutput extends z.ZodType = z.ZodVoid,
|
|
49
|
+
TContext = OperationContext,
|
|
39
50
|
>({
|
|
40
51
|
handle,
|
|
41
52
|
input,
|
|
42
53
|
output,
|
|
43
54
|
}: {
|
|
44
|
-
handle: OperationDefinition<TInput, TOutput>["handle"];
|
|
55
|
+
handle: OperationDefinition<TInput, TOutput, TContext>["handle"];
|
|
45
56
|
input: TInput;
|
|
46
57
|
output?: TOutput;
|
|
47
|
-
}): OperationDefinition<TInput
|
|
58
|
+
}): OperationDefinition<NoInfer<TInput>, NoInfer<TOutput>, TContext> => ({
|
|
48
59
|
handle,
|
|
49
60
|
input,
|
|
50
61
|
output: (output ?? z.void()) as TOutput,
|
|
@@ -53,26 +64,28 @@ export const defineOperation = <
|
|
|
53
64
|
export type QueryResourceDefinition<
|
|
54
65
|
TInput extends z.ZodType = z.ZodType,
|
|
55
66
|
TOutput extends z.ZodType = z.ZodType,
|
|
67
|
+
TContext = HandlerContext,
|
|
56
68
|
> = {
|
|
57
69
|
contract: ResourceContract<TInput, TOutput>;
|
|
58
70
|
kind: "query";
|
|
59
71
|
read: (
|
|
60
72
|
input: z.output<TInput>,
|
|
61
|
-
context:
|
|
73
|
+
context: TContext,
|
|
62
74
|
) => Promise<z.input<NoInfer<TOutput>>> | z.input<NoInfer<TOutput>>;
|
|
63
75
|
};
|
|
64
76
|
|
|
65
77
|
export type SubscriptionResourceDefinition<
|
|
66
78
|
TInput extends z.ZodType = z.ZodType,
|
|
67
79
|
TOutput extends z.ZodType = z.ZodType,
|
|
80
|
+
TContext = HandlerContext,
|
|
68
81
|
> = {
|
|
69
82
|
contract: ResourceContract<TInput, TOutput>;
|
|
70
83
|
kind: "subscription";
|
|
71
|
-
read: QueryResourceDefinition<TInput, TOutput>["read"];
|
|
84
|
+
read: QueryResourceDefinition<TInput, TOutput, TContext>["read"];
|
|
72
85
|
subscribe: (
|
|
73
86
|
input: z.output<TInput>,
|
|
74
87
|
invalidate: () => void,
|
|
75
|
-
context:
|
|
88
|
+
context: TContext,
|
|
76
89
|
) => RuntimeDisposer;
|
|
77
90
|
};
|
|
78
91
|
|
|
@@ -93,8 +106,16 @@ export type DerivedResourceDefinition<
|
|
|
93
106
|
type AnyZodType = z.ZodType<any, any, any>;
|
|
94
107
|
|
|
95
108
|
export type ResourceDefinition =
|
|
96
|
-
| QueryResourceDefinition<
|
|
97
|
-
|
|
109
|
+
| QueryResourceDefinition<
|
|
110
|
+
AnyZodType,
|
|
111
|
+
AnyZodType,
|
|
112
|
+
HandlerContext<ResourceInputMap>
|
|
113
|
+
>
|
|
114
|
+
| SubscriptionResourceDefinition<
|
|
115
|
+
AnyZodType,
|
|
116
|
+
AnyZodType,
|
|
117
|
+
HandlerContext<ResourceInputMap>
|
|
118
|
+
>
|
|
98
119
|
| DerivedResourceDefinition<AnyZodType, AnyZodType, any, any>;
|
|
99
120
|
|
|
100
121
|
export type StreamSession<TClientMessage = unknown> = {
|
|
@@ -106,11 +127,12 @@ export type StreamHandlerDefinition<
|
|
|
106
127
|
TInput extends z.ZodType = z.ZodType,
|
|
107
128
|
TClientMessage extends z.ZodType = z.ZodType,
|
|
108
129
|
TServerMessage extends z.ZodType = z.ZodType,
|
|
130
|
+
TContext = HandlerContext,
|
|
109
131
|
> = {
|
|
110
132
|
contract: StreamContract<TInput, TClientMessage, TServerMessage>;
|
|
111
133
|
open: (
|
|
112
134
|
input: z.output<TInput>,
|
|
113
|
-
context:
|
|
135
|
+
context: TContext & {
|
|
114
136
|
emit: (message: z.input<NoInfer<TServerMessage>>) => void;
|
|
115
137
|
fail: (cause: unknown) => void;
|
|
116
138
|
},
|
|
@@ -123,10 +145,21 @@ export const defineStreamHandler = <
|
|
|
123
145
|
TInput extends z.ZodType,
|
|
124
146
|
TClientMessage extends z.ZodType,
|
|
125
147
|
TServerMessage extends z.ZodType,
|
|
148
|
+
TContext = HandlerContext,
|
|
126
149
|
>(
|
|
127
150
|
contract: StreamContract<TInput, TClientMessage, TServerMessage>,
|
|
128
|
-
open: StreamHandlerDefinition<
|
|
129
|
-
|
|
151
|
+
open: StreamHandlerDefinition<
|
|
152
|
+
TInput,
|
|
153
|
+
TClientMessage,
|
|
154
|
+
TServerMessage,
|
|
155
|
+
TContext
|
|
156
|
+
>["open"],
|
|
157
|
+
): StreamHandlerDefinition<
|
|
158
|
+
TInput,
|
|
159
|
+
TClientMessage,
|
|
160
|
+
TServerMessage,
|
|
161
|
+
TContext
|
|
162
|
+
> => ({
|
|
130
163
|
contract,
|
|
131
164
|
open,
|
|
132
165
|
});
|
|
@@ -136,6 +169,10 @@ type ResourceContracts = Record<
|
|
|
136
169
|
ResourceContract<AnyZodType, AnyZodType>
|
|
137
170
|
>;
|
|
138
171
|
|
|
172
|
+
type ResourceInputs<TContracts extends ResourceContracts> = {
|
|
173
|
+
[TId in keyof TContracts]: z.input<TContracts[TId]["input"]>;
|
|
174
|
+
};
|
|
175
|
+
|
|
139
176
|
type DependencyOutputs<
|
|
140
177
|
TContracts extends ResourceContracts,
|
|
141
178
|
TDependencies extends Record<string, unknown>,
|
|
@@ -154,17 +191,29 @@ type DependencySource<TDependencies> = {
|
|
|
154
191
|
: { dependencies?: never };
|
|
155
192
|
};
|
|
156
193
|
|
|
157
|
-
type QueryFor<
|
|
194
|
+
type QueryFor<
|
|
195
|
+
TContract extends ResourceContract<AnyZodType, AnyZodType>,
|
|
196
|
+
TContracts extends ResourceContracts,
|
|
197
|
+
> = {
|
|
158
198
|
contract: TContract;
|
|
159
199
|
} & Omit<
|
|
160
|
-
QueryResourceDefinition<
|
|
200
|
+
QueryResourceDefinition<
|
|
201
|
+
TContract["input"],
|
|
202
|
+
TContract["output"],
|
|
203
|
+
HandlerContext<ResourceInputs<NoInfer<TContracts>>>
|
|
204
|
+
>,
|
|
161
205
|
"contract"
|
|
162
206
|
>;
|
|
163
207
|
|
|
164
208
|
type SubscriptionFor<
|
|
165
209
|
TContract extends ResourceContract<AnyZodType, AnyZodType>,
|
|
210
|
+
TContracts extends ResourceContracts,
|
|
166
211
|
> = { contract: TContract } & Omit<
|
|
167
|
-
SubscriptionResourceDefinition<
|
|
212
|
+
SubscriptionResourceDefinition<
|
|
213
|
+
TContract["input"],
|
|
214
|
+
TContract["output"],
|
|
215
|
+
HandlerContext<ResourceInputs<NoInfer<TContracts>>>
|
|
216
|
+
>,
|
|
168
217
|
"contract"
|
|
169
218
|
>;
|
|
170
219
|
|
|
@@ -186,8 +235,8 @@ type ConfiguredResource<
|
|
|
186
235
|
TDependencies,
|
|
187
236
|
TId extends keyof TContracts,
|
|
188
237
|
> =
|
|
189
|
-
| QueryFor<TContracts[TId]>
|
|
190
|
-
| SubscriptionFor<TContracts[TId]>
|
|
238
|
+
| QueryFor<TContracts[TId], TContracts>
|
|
239
|
+
| SubscriptionFor<TContracts[TId], TContracts>
|
|
191
240
|
| (TId extends keyof TDependencies
|
|
192
241
|
? TDependencies[TId] extends Record<
|
|
193
242
|
string,
|
|
@@ -213,26 +262,97 @@ export type AuthDuration = `${number}${"m" | "h" | "d"}`;
|
|
|
213
262
|
export type AuthConfigDefinition = {
|
|
214
263
|
mode: "cli-login";
|
|
215
264
|
origins?: string[];
|
|
216
|
-
sessionLifetime?: "
|
|
265
|
+
sessionLifetime?: "forever" | AuthDuration;
|
|
217
266
|
trustedProxyPeer?: string;
|
|
218
267
|
};
|
|
219
268
|
|
|
220
269
|
export type ServerConfigDefinition = {
|
|
221
270
|
host?: string;
|
|
222
|
-
logFile?: string;
|
|
223
271
|
port?: number;
|
|
224
272
|
productionWebAssetsDir?: string;
|
|
225
273
|
watch?: boolean;
|
|
226
274
|
};
|
|
227
275
|
|
|
228
|
-
type StreamDefinitions = Readonly<
|
|
229
|
-
Record<
|
|
276
|
+
type StreamDefinitions<TContext = HandlerContext<ResourceInputMap>> = Readonly<
|
|
277
|
+
Record<
|
|
278
|
+
string,
|
|
279
|
+
StreamHandlerDefinition<AnyZodType, AnyZodType, AnyZodType, TContext>
|
|
280
|
+
>
|
|
230
281
|
>;
|
|
231
282
|
|
|
232
283
|
type OperationDefinitions = Readonly<
|
|
233
|
-
Record<
|
|
284
|
+
Record<
|
|
285
|
+
string,
|
|
286
|
+
OperationDefinition<
|
|
287
|
+
AnyZodType,
|
|
288
|
+
AnyZodType,
|
|
289
|
+
OperationContext<ResourceInputMap>
|
|
290
|
+
>
|
|
291
|
+
>
|
|
234
292
|
>;
|
|
235
293
|
|
|
294
|
+
type OperationInputs = Record<string, AnyZodType>;
|
|
295
|
+
|
|
296
|
+
type OperationOutputSchema<
|
|
297
|
+
TOutputs,
|
|
298
|
+
TId extends PropertyKey,
|
|
299
|
+
> = TId extends keyof TOutputs
|
|
300
|
+
? TOutputs[TId] extends z.ZodType
|
|
301
|
+
? TOutputs[TId]
|
|
302
|
+
: z.ZodVoid
|
|
303
|
+
: z.ZodVoid;
|
|
304
|
+
|
|
305
|
+
type ConfiguredOperations<
|
|
306
|
+
TInputs extends OperationInputs,
|
|
307
|
+
TOutputs,
|
|
308
|
+
TContracts extends ResourceContracts,
|
|
309
|
+
> = {
|
|
310
|
+
[TId in keyof TInputs]: {
|
|
311
|
+
input: TInputs[TId];
|
|
312
|
+
output?: OperationOutputSchema<TOutputs, TId>;
|
|
313
|
+
handle: OperationDefinition<
|
|
314
|
+
TInputs[TId],
|
|
315
|
+
OperationOutputSchema<TOutputs, TId>,
|
|
316
|
+
OperationContext<ResourceInputs<TContracts>>
|
|
317
|
+
>["handle"];
|
|
318
|
+
};
|
|
319
|
+
} & {
|
|
320
|
+
[TId in keyof TOutputs]: TOutputs[TId] extends z.ZodType
|
|
321
|
+
? { output: TOutputs[TId] }
|
|
322
|
+
: { output?: never };
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
type NormalizedOperations<
|
|
326
|
+
TInputs extends OperationInputs,
|
|
327
|
+
TOutputs,
|
|
328
|
+
TContracts extends ResourceContracts,
|
|
329
|
+
> = {
|
|
330
|
+
[TId in keyof TInputs]: OperationDefinition<
|
|
331
|
+
TInputs[TId],
|
|
332
|
+
OperationOutputSchema<TOutputs, TId>,
|
|
333
|
+
OperationContext<ResourceInputs<TContracts>>
|
|
334
|
+
>;
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
const normalizeOperations = <
|
|
338
|
+
TInputs extends OperationInputs,
|
|
339
|
+
TOutputs,
|
|
340
|
+
TContracts extends ResourceContracts,
|
|
341
|
+
>(
|
|
342
|
+
operations: ConfiguredOperations<TInputs, TOutputs, TContracts> | undefined,
|
|
343
|
+
): NormalizedOperations<TInputs, TOutputs, TContracts> | undefined => {
|
|
344
|
+
if (operations === undefined) {
|
|
345
|
+
return undefined;
|
|
346
|
+
}
|
|
347
|
+
// Preserve every key and handler; only absent output schemas become ZodVoid.
|
|
348
|
+
return Object.fromEntries(
|
|
349
|
+
Object.entries(operations).map(([id, definition]) => [
|
|
350
|
+
id,
|
|
351
|
+
{ ...definition, output: definition.output ?? z.void() },
|
|
352
|
+
]),
|
|
353
|
+
) as NormalizedOperations<TInputs, TOutputs, TContracts>;
|
|
354
|
+
};
|
|
355
|
+
|
|
236
356
|
export type ConfigDefinition<
|
|
237
357
|
TResources extends Readonly<Record<string, unknown>> = Readonly<
|
|
238
358
|
Record<string, ResourceDefinition>
|
|
@@ -278,16 +398,21 @@ export const defineOvermuxServer = <
|
|
|
278
398
|
const TContracts extends ResourceContracts = {},
|
|
279
399
|
const TDependencies = {},
|
|
280
400
|
const TStreams extends StreamDefinitions = {},
|
|
281
|
-
const
|
|
401
|
+
const TInputs extends OperationInputs = {},
|
|
402
|
+
const TOutputs = {},
|
|
282
403
|
>(definition: {
|
|
283
|
-
operations?:
|
|
404
|
+
operations?: ConfiguredOperations<TInputs, TOutputs, NoInfer<TContracts>>;
|
|
284
405
|
resources: ConfiguredResources<TContracts, TDependencies>;
|
|
285
|
-
streams?: TStreams
|
|
406
|
+
streams?: TStreams &
|
|
407
|
+
StreamDefinitions<HandlerContext<ResourceInputs<NoInfer<TContracts>>>>;
|
|
286
408
|
}): ConfigDefinition<
|
|
287
409
|
ConfiguredResources<TContracts, TDependencies>,
|
|
288
410
|
TStreams,
|
|
289
|
-
|
|
290
|
-
> =>
|
|
411
|
+
NormalizedOperations<TInputs, TOutputs, TContracts>
|
|
412
|
+
> => ({
|
|
413
|
+
...definition,
|
|
414
|
+
operations: normalizeOperations(definition.operations),
|
|
415
|
+
});
|
|
291
416
|
|
|
292
417
|
export const defineOvermuxConfig = <const TServer extends ConfigDefinition>(
|
|
293
418
|
definition: OvermuxConfigDefinition<TServer>,
|
package/src/public/server.ts
CHANGED
|
@@ -1,16 +1 @@
|
|
|
1
|
-
export {
|
|
2
|
-
checkOvermux,
|
|
3
|
-
type CheckDiagnostic,
|
|
4
|
-
type CheckOvermuxOptions,
|
|
5
|
-
type CheckResult,
|
|
6
|
-
} from "../internal/server/check-overmux";
|
|
7
|
-
export {
|
|
8
|
-
getOvermuxPaths,
|
|
9
|
-
type GetOvermuxPathsOptions,
|
|
10
|
-
type OvermuxPaths,
|
|
11
|
-
} from "../internal/server/paths";
|
|
12
|
-
export {
|
|
13
|
-
startOvermuxServer,
|
|
14
|
-
type OvermuxServer,
|
|
15
|
-
type OvermuxServerOptions,
|
|
16
|
-
} from "../internal/server/start-overmux-server";
|
|
1
|
+
export { getOvermuxPaths } from "../internal/server/paths";
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Project Structure
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
`overmux init` creates this minimal userland application:
|
|
6
|
-
|
|
7
|
-
```text
|
|
8
|
-
.gitignore
|
|
9
|
-
mise.toml Mise installations only
|
|
10
|
-
package.json
|
|
11
|
-
pnpm-lock.yaml
|
|
12
|
-
overmux.config.ts authentication, server, Vite, and production settings
|
|
13
|
-
src/server/index.ts trusted resources, streams, and operations
|
|
14
|
-
src/ui/app.tsx browser application definition
|
|
15
|
-
src/ui/index.html browser document
|
|
16
|
-
src/ui/main.tsx React and Overmux host entry point
|
|
17
|
-
src/ui/styles.css application styles
|
|
18
|
-
vite.config.ts browser development and production build configuration
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
The server and UI are separate trust boundaries. `src/server/index.ts` runs as trusted Node.js code. Files under `src/ui` run in the browser and communicate with the server through Overmux's public APIs.
|
|
22
|
-
|
|
23
|
-
The generated application has no shared directory. Add browser-safe shared schemas only when both sides need them.
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Theming
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
## Host and platform selectors
|
|
6
|
-
|
|
7
|
-
Overmux sets two independent attributes on the hosted application's `<html>` element before React mounts:
|
|
8
|
-
|
|
9
|
-
```html
|
|
10
|
-
<html data-om-host="desktop" data-om-platform="macos">
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Use these public CSS selectors to adapt your application to its environment:
|
|
14
|
-
|
|
15
|
-
```css
|
|
16
|
-
/* Hide browser-only installation guidance in native and installed apps. */
|
|
17
|
-
html:not([data-om-host="browser"]) .install-prompt {
|
|
18
|
-
display: none;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/* OS-specific styling also works when using Overmux in a browser. */
|
|
22
|
-
html[data-om-platform="macos"] .shortcut-hint {
|
|
23
|
-
font-family: system-ui;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/* Combine the independent host and platform selectors. */
|
|
27
|
-
html[data-om-host="desktop"][data-om-platform="windows"] .app-toolbar {
|
|
28
|
-
padding-inline: 1rem;
|
|
29
|
-
}
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### Host values
|
|
33
|
-
|
|
34
|
-
| `data-om-host` | Meaning |
|
|
35
|
-
| --- | --- |
|
|
36
|
-
| `desktop` | Running inside the native Overmux desktop host, regardless of window size. |
|
|
37
|
-
| `browser` | Running in a regular browser tab or window. |
|
|
38
|
-
| `pwa` | Running as an installed web app in `standalone`, `minimal-ui`, or `window-controls-overlay` display mode, including Safari's installed standalone mode. |
|
|
39
|
-
|
|
40
|
-
A progressive web app (PWA) is a website that can run as an installed application. Visiting an installable website does not make the host `pwa`. Ordinary browser fullscreen does not qualify either. Native desktop detection takes precedence over display mode. Browser/PWA selectors update when the supported display modes change.
|
|
41
|
-
|
|
42
|
-
`desktop` describes the host, not a desktop-sized layout. Use CSS media or container queries for responsive layout. The native host's implementation technology is not a CSS value.
|
|
43
|
-
|
|
44
|
-
### Platform values
|
|
45
|
-
|
|
46
|
-
`data-om-platform` is always one of `macos`, `windows`, `linux`, `android`, `ios`, or `unknown`.
|
|
47
|
-
|
|
48
|
-
The native desktop host supplies its OS identity through versioned preload metadata. Browsers use best-effort detection from browser-provided platform and user-agent information, including touch-capable iPads presenting a Mac identity. Missing, obscured, or unrecognized information can yield `unknown`; do not use these selectors for security decisions or feature detection.
|
|
49
|
-
|
|
50
|
-
### Scope
|
|
51
|
-
|
|
52
|
-
These attributes belong to the hosted application document, independently of `OvermuxThemeScope`. They do not change theme tokens, color scheme, contrast, nested theme scopes, or portal inheritance. Selectors anchored at `html` also match portal content in the same document, including caller-owned external portal containers.
|
|
53
|
-
|
|
54
|
-
This API does not theme native window controls or the desktop connection screen. It requires no public JavaScript API; use the attributes directly in your application's CSS.
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Configuration
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
## Instance identity
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
import { defineOvermuxConfig } from "overmux";
|
|
9
|
-
import { server } from "./server";
|
|
10
|
-
|
|
11
|
-
export default defineOvermuxConfig({
|
|
12
|
-
server,
|
|
13
|
-
instanceId: ({ port }) => `rich-work-${port}`,
|
|
14
|
-
});
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
`instanceId` accepts a fixed string (for example `instanceId: "rich-work"`) or a function of `{ port }`. It is resolved once at server startup using the actual listening port. Every hostname serving this running instance reports the same ID. Changing the port intentionally changes a port-dependent ID.
|
|
18
|
-
|
|
19
|
-
`port` in `overmux.config.ts` must be an integer from `1` through `65535`. Internal listeners and tests may use `0` to ask the OS for a free port; this is not a user configuration value.
|
|
20
|
-
|
|
21
|
-
The default is the machine hostname followed by `-<port>`. IDs are canonical lowercase ASCII: 1-253 characters, start and end with a letter or digit, and may contain dots or hyphens internally. Explicit IDs are validated, never silently normalized. Set an explicit ID if the machine hostname does not meet these rules.
|
|
22
|
-
|
|
23
|
-
Distinct instances require distinct IDs. IDs are names, not credentials; authentication is still required. Deep links use `overmux://<instance-id>/<application-route>`. Their authority is only a lookup key, never a network address. Use the live runtime helpers or `overmux instance --json` to produce a prefix rather than guessing it from a browser URL.
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Server API
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
## Instance identity in handlers
|
|
6
|
-
|
|
7
|
-
Operation, resource, and stream handler contexts expose the running instance:
|
|
8
|
-
|
|
9
|
-
```ts
|
|
10
|
-
import { defineOperation } from "overmux";
|
|
11
|
-
import { z } from "zod";
|
|
12
|
-
|
|
13
|
-
export const paneLink = defineOperation({
|
|
14
|
-
input: z.object({ paneId: z.string() }),
|
|
15
|
-
output: z.string(),
|
|
16
|
-
handle: ({ paneId }, context) =>
|
|
17
|
-
`${context.instance.getDeepLinkPrefix()}/panes/${encodeURIComponent(paneId)}`,
|
|
18
|
-
});
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
`context.instance.getInstanceId(): string` and `context.instance.getDeepLinkPrefix(): string` are synchronous and ready before handlers execute. They belong to this server runtime, not process-global state. The prefix is exactly `overmux://<instance-id>` without a trailing slash. Encode route segments once, not the whole assembled URL.
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Client API
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
## Instance identity
|
|
6
|
-
|
|
7
|
-
```tsx
|
|
8
|
-
import { createOvermuxHooks } from "overmux/client";
|
|
9
|
-
import type { serverConfig } from "./server";
|
|
10
|
-
|
|
11
|
-
const { useInstance } = createOvermuxHooks<typeof serverConfig>();
|
|
12
|
-
|
|
13
|
-
const PaneLink = ({ paneId }: { paneId: string }) => {
|
|
14
|
-
const instance = useInstance();
|
|
15
|
-
if (!instance) return null;
|
|
16
|
-
return <a href={`${instance.deepLinkPrefix}/panes/${encodeURIComponent(paneId)}`}>Open pane in desktop</a>;
|
|
17
|
-
};
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
Use these hooks under the existing Overmux provider. `useInstance()` returns `{ instanceId, deepLinkPrefix } | undefined` and rerenders when authenticated discovery arrives or changes after reconnecting.
|
|
21
|
-
|
|
22
|
-
The same scoped `overmuxServerApi` object passed to command handlers for operations also provides `overmuxServerApi.getInstanceId()` and `overmuxServerApi.getDeepLinkPrefix()`. Both return `undefined` until the authenticated server announces its identity. The prefix is exactly `overmux://<instance-id>`, without a trailing slash. Browser addresses are not instance identities. Desktop hosts receive discovery through a narrow identity bridge automatically; application code does not need to forward it.
|
|
23
|
-
|
|
24
|
-
## Clipboard
|
|
25
|
-
|
|
26
|
-
```ts
|
|
27
|
-
import { readClipboardText, writeClipboardText } from "overmux/client";
|
|
28
|
-
|
|
29
|
-
await writeClipboardText("Text to copy");
|
|
30
|
-
const text = await readClipboardText();
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
`readClipboardText(): Promise<string>` reads the system clipboard through `navigator.clipboard.readText()`. It never reads through the desktop bridge.
|
|
34
|
-
|
|
35
|
-
`writeClipboardText(text: string): Promise<void>` uses Overmux's version-1 desktop write bridge when present, otherwise `navigator.clipboard.writeText()`. Desktop writes are fire-and-forget: resolution confirms dispatch, not completion or acceptance by the host. Existing host origin and active-frame checks still apply.
|
|
36
|
-
|
|
37
|
-
Both reject on unavailable browser APIs, browser permission failures, or synchronous desktop dispatch failures. Browser secure-context, focus, permissions, and user-activation restrictions still apply. These APIs target the system clipboard, not the X11 primary selection. Only read clipboard data you need and trust the source of text you write.
|
|
38
|
-
|
|
39
|
-
For terminal-program access via OSC 52, use the opt-in factories from `@overmux/xterm/client` rather than wiring platform bridges in application code.
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "overmux check"
|
|
3
|
-
description: "Validate an Overmux configuration"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# `overmux check`
|
|
7
|
-
|
|
8
|
-
Validate an Overmux configuration.
|
|
9
|
-
|
|
10
|
-
## Usage
|
|
11
|
-
|
|
12
|
-
```text
|
|
13
|
-
overmux check [--config path]
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## Options
|
|
17
|
-
|
|
18
|
-
| Flag | Description | Default |
|
|
19
|
-
| --- | --- | --- |
|
|
20
|
-
| `--config <path>, -c <path>` | Configuration file | `$XDG_CONFIG_HOME/overmux/overmux.config.ts` |
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "overmux ai context"
|
|
3
|
-
description: "Set up your coding agent and configure its Overmux context"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# `overmux ai context`
|
|
7
|
-
|
|
8
|
-
Print version-aware Overmux guidance for coding agents as Markdown.
|
|
9
|
-
|
|
10
|
-
## Usage
|
|
11
|
-
|
|
12
|
-
```text
|
|
13
|
-
overmux ai context [--config path]
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## Set up your coding agent
|
|
17
|
-
|
|
18
|
-
Add a short instruction that tells your agent how to load the context when it needs Overmux guidance:
|
|
19
|
-
|
|
20
|
-
<CodeBlockTabs defaultValue="agents">
|
|
21
|
-
<CodeBlockTabsList>
|
|
22
|
-
<CodeBlockTabsTrigger value="agents">AGENTS.md</CodeBlockTabsTrigger>
|
|
23
|
-
<CodeBlockTabsTrigger value="claude">CLAUDE.md</CodeBlockTabsTrigger>
|
|
24
|
-
</CodeBlockTabsList>
|
|
25
|
-
<CodeBlockTab value="agents">
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
echo 'Run `overmux ai context` for help configuring Overmux.' >> AGENTS.md
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
</CodeBlockTab>
|
|
32
|
-
<CodeBlockTab value="claude">
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
echo 'Run `overmux ai context` for help configuring Overmux.' >> CLAUDE.md
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
</CodeBlockTab>
|
|
39
|
-
</CodeBlockTabs>
|
|
40
|
-
|
|
41
|
-
## Configure context snippets
|
|
42
|
-
|
|
43
|
-
Set `aiContextSnippets` in `$XDG_CONFIG_HOME/overmux/overmux.config.ts` to choose the guidance included in the command output:
|
|
44
|
-
|
|
45
|
-
```ts
|
|
46
|
-
import {
|
|
47
|
-
coreAiContextSnippets,
|
|
48
|
-
defineOvermuxConfig,
|
|
49
|
-
} from "overmux";
|
|
50
|
-
|
|
51
|
-
export default defineOvermuxConfig({
|
|
52
|
-
aiContextSnippets: coreAiContextSnippets,
|
|
53
|
-
// ...
|
|
54
|
-
});
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
When `aiContextSnippets` is omitted, Overmux uses `defaultAiContextSnippets`. Set it to an empty array to emit no context.
|
|
58
|
-
|
|
59
|
-
## Options
|
|
60
|
-
|
|
61
|
-
| Flag | Description | Default |
|
|
62
|
-
| --- | --- | --- |
|
|
63
|
-
| `--config <path>, -c <path>` | Configuration file | `$XDG_CONFIG_HOME/overmux/overmux.config.ts` |
|
|
64
|
-
|
|
65
|
-
## Preset groups
|
|
66
|
-
|
|
67
|
-
| Export | Included snippets |
|
|
68
|
-
| --- | --- |
|
|
69
|
-
| `defaultAiContextSnippets` | `package-source`, `tech-stack-recommendations` |
|
|
70
|
-
| `coreAiContextSnippets` | `package-source` |
|
|
71
|
-
|
|
72
|
-
## Snippet reference
|
|
73
|
-
|
|
74
|
-
### `package-source`
|
|
75
|
-
|
|
76
|
-
Export: `packageSourceSnippet`
|
|
77
|
-
|
|
78
|
-
Included in the core and default presets. Tells agents to inspect the documentation and TypeScript source shipped in installed Overmux packages so their guidance matches the versions used by the application.
|
|
79
|
-
|
|
80
|
-
### `tech-stack-recommendations`
|
|
81
|
-
|
|
82
|
-
Export: `techStackRecommendationsSnippet`
|
|
83
|
-
|
|
84
|
-
Included in the default preset. Recommends pnpm, TanStack Router, shadcn/ui, and Zod while deferring to the application's established stack.
|
|
85
|
-
|
|
86
|
-
You can compose an explicit selection from the individual exports:
|
|
87
|
-
|
|
88
|
-
```ts
|
|
89
|
-
import {
|
|
90
|
-
defineOvermuxConfig,
|
|
91
|
-
packageSourceSnippet,
|
|
92
|
-
techStackRecommendationsSnippet,
|
|
93
|
-
} from "overmux";
|
|
94
|
-
|
|
95
|
-
export default defineOvermuxConfig({
|
|
96
|
-
aiContextSnippets: [
|
|
97
|
-
packageSourceSnippet,
|
|
98
|
-
techStackRecommendationsSnippet,
|
|
99
|
-
],
|
|
100
|
-
// ...
|
|
101
|
-
});
|
|
102
|
-
```
|