overmux 0.0.2 → 0.0.4
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 +21 -0
- package/dist/auth/.vite/manifest.json +2 -2
- package/dist/auth/assets/{index-Bx8JhwVi.css → index-BM9gETvx.css} +1 -1
- package/dist/auth/assets/{index-CHIE7qYj.js → index-DabAfcs1.js} +1 -1
- package/dist/auth/index.html +2 -2
- package/dist/bin.js +430 -18
- package/dist/bin.js.map +1 -1
- package/dist/docs/200-getting-started/100-install-and-run-overmux.md +1 -2
- package/dist/docs/300-fundamentals/100-project-structure.md +20 -0
- package/dist/docs/300-fundamentals/300-theming.md +51 -0
- package/dist/docs/400-reference/100-configuration.md +20 -0
- package/dist/docs/400-reference/200-server-api.md +18 -0
- package/dist/docs/400-reference/300-client-api.md +36 -0
- package/dist/docs/400-reference/400-cli/050-init.md +17 -0
- package/dist/docs/400-reference/400-cli/350-instance.md +24 -0
- package/dist/exports/client.d.ts +33 -3
- package/dist/exports/client.d.ts.map +1 -1
- package/dist/exports/client.js +123 -14
- package/dist/exports/client.js.map +1 -1
- package/dist/exports/{index-D3_Dpy_T.d.ts → index-DS70rKzo.d.ts} +14 -2
- package/dist/exports/index-DS70rKzo.d.ts.map +1 -0
- package/dist/exports/index.d.ts +2 -2
- package/dist/exports/index.js +1 -1
- package/dist/exports/index.js.map +1 -1
- package/dist/exports/{notifications-kDp16bU_.js → notifications-av0FK0yZ.js} +7 -2
- package/dist/exports/{notifications-kDp16bU_.js.map → notifications-av0FK0yZ.js.map} +1 -1
- package/dist/exports/server.d.ts.map +1 -1
- package/dist/exports/server.js +52 -10
- package/dist/exports/server.js.map +1 -1
- package/dist/internal/server/coordinator/server-child.js +110 -46
- package/dist/internal/server/coordinator/server-child.js.map +1 -1
- package/docs/200-getting-started/100-install-and-run-overmux.md +1 -2
- package/docs/300-fundamentals/100-project-structure.md +20 -0
- package/docs/300-fundamentals/300-theming.md +51 -0
- package/docs/400-reference/100-configuration.md +20 -0
- package/docs/400-reference/200-server-api.md +18 -0
- package/docs/400-reference/300-client-api.md +36 -0
- package/docs/400-reference/400-cli/050-init.md +17 -0
- package/docs/400-reference/400-cli/350-instance.md +24 -0
- package/package.json +2 -2
- package/src/internal/cli/app.ts +7 -1
- package/src/internal/cli/commands/init-template.ts +146 -0
- package/src/internal/cli/commands/init.ts +267 -0
- package/src/internal/cli/commands/instance.ts +58 -0
- package/src/internal/cli/commands/integration.ts +15 -0
- package/src/internal/cli/commands/zellij-install.ts +96 -0
- package/src/internal/cli/parse-port.ts +2 -1
- package/src/internal/client/auth/auth-shell.css +17 -1
- package/src/internal/client/auth/auth-shell.tsx +2 -11
- package/src/internal/client/auth/login-code-input.tsx +140 -0
- package/src/internal/client/browser-api.ts +17 -3
- package/src/internal/client/clipboard.ts +22 -0
- package/src/internal/client/host/desktop-host.ts +15 -0
- package/src/internal/client/host/environment.ts +67 -0
- package/src/internal/client/host/instance-forwarding.ts +21 -0
- package/src/internal/client/host/notification-forwarding.ts +1 -10
- package/src/internal/client/host/overmux-host.tsx +8 -0
- package/src/internal/client/overmux-react.ts +24 -2
- package/src/internal/client/websocket.ts +48 -20
- package/src/internal/server/auth/instance-control.ts +24 -3
- package/src/internal/server/runtime/create-runtime.ts +12 -1
- package/src/internal/server/runtime/runtime-instance.ts +46 -0
- package/src/internal/server/runtime/runtime-resources.ts +3 -0
- package/src/internal/server/server-startup-options.ts +9 -4
- package/src/internal/server/start-application-server.ts +20 -12
- package/src/internal/server/websocket-server.ts +7 -0
- package/src/internal/shared/index.ts +2 -0
- package/src/internal/shared/protocol.ts +10 -1
- package/src/public/client.ts +5 -0
- package/src/public/config.ts +7 -0
- package/src/public/index.ts +2 -0
- package/dist/exports/index-D3_Dpy_T.d.ts.map +0 -1
package/dist/bin.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { createRequire } from "node:module";
|
|
2
|
+
import { createRequire, findPackageJSON } from "node:module";
|
|
3
3
|
import { access, chmod, readFile, readdir, realpath } from "node:fs/promises";
|
|
4
4
|
import { createConnection, isIP } from "node:net";
|
|
5
5
|
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
6
6
|
import { createJiti } from "jiti";
|
|
7
7
|
import { ZodError, z } from "zod";
|
|
8
|
-
import { homedir, tmpdir } from "node:os";
|
|
8
|
+
import { homedir, hostname, tmpdir } from "node:os";
|
|
9
9
|
import { createHash } from "node:crypto";
|
|
10
10
|
import ts from "typescript";
|
|
11
11
|
import { isDeepStrictEqual } from "node:util";
|
|
12
12
|
import { fork, spawnSync } from "node:child_process";
|
|
13
13
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
14
|
-
import { createWriteStream, existsSync, lstatSync, mkdirSync, mkdtempSync, readdirSync, readlinkSync, renameSync, rmSync, watch } from "node:fs";
|
|
14
|
+
import { cpSync, createWriteStream, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, readlinkSync, renameSync, rmSync, statSync, watch, writeFileSync } from "node:fs";
|
|
15
15
|
import { createInterface } from "node:readline/promises";
|
|
16
16
|
import { Readable, Transform } from "node:stream";
|
|
17
17
|
import { pipeline } from "node:stream/promises";
|
|
@@ -877,7 +877,7 @@ function listAllRouteNamesAndAliasesForScan(routeMap, scannerCaseStyle, config)
|
|
|
877
877
|
return [routeName];
|
|
878
878
|
});
|
|
879
879
|
}
|
|
880
|
-
async function runCommand$
|
|
880
|
+
async function runCommand$2({ loader, parameters }, { context, inputs, scannerConfig, errorFormatting, determineExitCode, ansiColorByStream }) {
|
|
881
881
|
let parsedArguments;
|
|
882
882
|
try {
|
|
883
883
|
const scanner = buildArgumentScanner(parameters, scannerConfig);
|
|
@@ -1348,7 +1348,7 @@ async function scanInputsAndRunTarget(app, rawInputs, context, text, ansiColorBy
|
|
|
1348
1348
|
result
|
|
1349
1349
|
});
|
|
1350
1350
|
if (typeof hookStartExitCode === "number") return hookStartExitCode;
|
|
1351
|
-
const exitCode = await runCommand$
|
|
1351
|
+
const exitCode = await runCommand$2(result.target, {
|
|
1352
1352
|
context: commandContext,
|
|
1353
1353
|
inputs: result.unprocessedInputs,
|
|
1354
1354
|
scannerConfig: app.config.scanner,
|
|
@@ -1842,6 +1842,7 @@ var durationToMilliseconds = (duration) => {
|
|
|
1842
1842
|
return Number.isSafeInteger(milliseconds) ? milliseconds : void 0;
|
|
1843
1843
|
};
|
|
1844
1844
|
var aiContextSnippets = ["package-source", "tech-stack-recommendations"];
|
|
1845
|
+
var instanceIdSchema$1 = z.string().max(253).regex(/^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?(?![\s\S])/, "Expected a lowercase instance ID with only ASCII letters, digits, internal dots and hyphens");
|
|
1845
1846
|
var zodTypeSchema = z.custom((value) => value instanceof z.ZodType, "Expected a Zod schema");
|
|
1846
1847
|
var functionSchema = z.custom((value) => typeof value === "function", "Expected a function");
|
|
1847
1848
|
var contractRuntimeSchema = z.object({
|
|
@@ -1909,6 +1910,7 @@ var configDefinitionRuntimeSchema = serverConfigRuntimeSchema.extend({
|
|
|
1909
1910
|
aiContextSnippets: z.array(z.enum(aiContextSnippets)).optional(),
|
|
1910
1911
|
auth: authConfigRuntimeSchema,
|
|
1911
1912
|
debug: z.boolean().optional(),
|
|
1913
|
+
instanceId: z.union([instanceIdSchema$1, z.custom((value) => typeof value === "function", "Expected an instance ID or a function of the bound port")]).optional(),
|
|
1912
1914
|
server: serverDefinitionRuntimeSchema,
|
|
1913
1915
|
vite: z.string().min(1).optional()
|
|
1914
1916
|
});
|
|
@@ -1989,6 +1991,11 @@ var notificationSchema = z.object({
|
|
|
1989
1991
|
open: z.object({ link: notificationLinkSchema }).strict().optional(),
|
|
1990
1992
|
title: z.string().min(1).max(4096)
|
|
1991
1993
|
}).strict();
|
|
1994
|
+
var instanceIdSchema = z.string().max(253).regex(/^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?(?![\s\S])/, "Expected a lowercase instance ID with only ASCII letters, digits, internal dots and hyphens");
|
|
1995
|
+
var createInstanceIdentity = (instanceId) => ({
|
|
1996
|
+
instanceId: instanceIdSchema.parse(instanceId),
|
|
1997
|
+
deepLinkPrefix: `overmux://${instanceId}`
|
|
1998
|
+
});
|
|
1992
1999
|
var defaultAiContextSnippets = [...[packageSourceSnippet], techStackRecommendationsSnippet];
|
|
1993
2000
|
var packageSourceSnippetContent = `Overmux ships with documentation and TypeScript source.
|
|
1994
2001
|
|
|
@@ -2047,6 +2054,7 @@ var readPrivateJson = async (path, schema) => {
|
|
|
2047
2054
|
//#region src/internal/server/auth/instance-control.ts
|
|
2048
2055
|
var maxControlMessageBytes = 16384;
|
|
2049
2056
|
z.discriminatedUnion("type", [
|
|
2057
|
+
z.object({ type: z.literal("get-instance") }).strict(),
|
|
2050
2058
|
z.object({ type: z.literal("ping") }).strict(),
|
|
2051
2059
|
z.object({ type: z.literal("create-login") }).strict(),
|
|
2052
2060
|
z.object({ type: z.literal("issue-bearer") }).strict(),
|
|
@@ -2072,6 +2080,10 @@ var sessionSchema = z.object({
|
|
|
2072
2080
|
revokedAt: z.string().optional()
|
|
2073
2081
|
}).strict();
|
|
2074
2082
|
var controlResponseSchemas = {
|
|
2083
|
+
"get-instance": z.object({
|
|
2084
|
+
instanceId: instanceIdSchema,
|
|
2085
|
+
ok: z.literal(true)
|
|
2086
|
+
}).strict(),
|
|
2075
2087
|
"create-login": z.object({
|
|
2076
2088
|
login: loginGrantSchema,
|
|
2077
2089
|
ok: z.literal(true)
|
|
@@ -2234,7 +2246,7 @@ var printLoginGrant = ({ login, output, port }) => {
|
|
|
2234
2246
|
//#region src/internal/cli/parse-port.ts
|
|
2235
2247
|
var parsePort = (value) => {
|
|
2236
2248
|
const port = Number(value);
|
|
2237
|
-
return serverConfigRuntimeSchema.shape.port.safeParse(port).success ? port : /* @__PURE__ */ new Error(`Invalid port: ${value}`);
|
|
2249
|
+
return port > 0 && serverConfigRuntimeSchema.shape.port.safeParse(port).success ? port : /* @__PURE__ */ new Error(`Invalid port: ${value}`);
|
|
2238
2250
|
};
|
|
2239
2251
|
//#endregion
|
|
2240
2252
|
//#region src/internal/cli/commands/auth.ts
|
|
@@ -2415,7 +2427,7 @@ z.object({ endpoint: backgroundNotificationSubscriptionSchema.shape.endpoint }).
|
|
|
2415
2427
|
z.object({
|
|
2416
2428
|
debug: z.boolean(),
|
|
2417
2429
|
operations: z.array(z.string().min(1)),
|
|
2418
|
-
protocolVersion: z.literal(
|
|
2430
|
+
protocolVersion: z.literal(10),
|
|
2419
2431
|
resources: z.array(z.string().min(1)),
|
|
2420
2432
|
streams: z.array(z.string().min(1))
|
|
2421
2433
|
});
|
|
@@ -2521,7 +2533,12 @@ var protocolErrorMessageSchema = z.object({
|
|
|
2521
2533
|
subscriptionId: operationIdSchema.optional(),
|
|
2522
2534
|
type: z.literal("error")
|
|
2523
2535
|
});
|
|
2536
|
+
var serverInfoMessageSchema = z.object({
|
|
2537
|
+
type: z.literal("server-info"),
|
|
2538
|
+
instanceId: instanceIdSchema
|
|
2539
|
+
}).strict();
|
|
2524
2540
|
z.discriminatedUnion("type", [
|
|
2541
|
+
serverInfoMessageSchema,
|
|
2525
2542
|
resourceResultMessageSchema,
|
|
2526
2543
|
resourceInvalidatedMessageSchema,
|
|
2527
2544
|
streamOpenedMessageSchema,
|
|
@@ -2533,6 +2550,30 @@ z.discriminatedUnion("type", [
|
|
|
2533
2550
|
notificationEventSchema
|
|
2534
2551
|
]);
|
|
2535
2552
|
//#endregion
|
|
2553
|
+
//#region src/internal/server/runtime/runtime-instance.ts
|
|
2554
|
+
var createRuntimeInstance = (configured) => {
|
|
2555
|
+
let identity;
|
|
2556
|
+
const get = () => {
|
|
2557
|
+
if (!identity) throw new Error("Overmux instance identity is not ready");
|
|
2558
|
+
return identity;
|
|
2559
|
+
};
|
|
2560
|
+
return {
|
|
2561
|
+
context: {
|
|
2562
|
+
getInstanceId: () => get().instanceId,
|
|
2563
|
+
getDeepLinkPrefix: () => get().deepLinkPrefix
|
|
2564
|
+
},
|
|
2565
|
+
establish: (port) => {
|
|
2566
|
+
if (identity) throw new Error("Overmux instance identity is already established");
|
|
2567
|
+
try {
|
|
2568
|
+
identity = createInstanceIdentity(typeof configured === "function" ? configured({ port }) : configured ?? `${hostname()}-${port}`);
|
|
2569
|
+
} catch (cause) {
|
|
2570
|
+
throw new Error("Invalid Overmux instance ID; configure instanceId with a canonical lowercase ID", { cause });
|
|
2571
|
+
}
|
|
2572
|
+
return identity;
|
|
2573
|
+
}
|
|
2574
|
+
};
|
|
2575
|
+
};
|
|
2576
|
+
//#endregion
|
|
2536
2577
|
//#region src/internal/server/runtime/runtime-lifecycle.ts
|
|
2537
2578
|
var asError = (cause) => cause instanceof Error ? cause : new Error(String(cause));
|
|
2538
2579
|
var disposeAll = async (disposers) => {
|
|
@@ -2699,7 +2740,7 @@ var getInvalidatedResourceIds = (graph, resourceId) => {
|
|
|
2699
2740
|
};
|
|
2700
2741
|
//#endregion
|
|
2701
2742
|
//#region src/internal/server/runtime/runtime-resources.ts
|
|
2702
|
-
var createRuntimeResources = ({ definitions, lifecycle }) => {
|
|
2743
|
+
var createRuntimeResources = ({ definitions, instance, lifecycle }) => {
|
|
2703
2744
|
const graph = createResourceDependencyGraph(definitions);
|
|
2704
2745
|
const invalidationListeners = /* @__PURE__ */ new Set();
|
|
2705
2746
|
const contracts = /* @__PURE__ */ new Map();
|
|
@@ -2724,6 +2765,7 @@ var createRuntimeResources = ({ definitions, lifecycle }) => {
|
|
|
2724
2765
|
});
|
|
2725
2766
|
};
|
|
2726
2767
|
const context = (signal) => ({
|
|
2768
|
+
instance,
|
|
2727
2769
|
invalidate,
|
|
2728
2770
|
signal: lifecycle.requestSignal(signal)
|
|
2729
2771
|
});
|
|
@@ -2858,9 +2900,11 @@ var createRuntimeStreams = ({ context, definitions, lifecycle }) => {
|
|
|
2858
2900
|
//#region src/internal/server/runtime/create-runtime.ts
|
|
2859
2901
|
var createRuntime = async ({ config, debug = false, notifications = { send: async () => void 0 }, signal }) => {
|
|
2860
2902
|
const lifecycle = createRuntimeLifecycle(signal);
|
|
2903
|
+
const instance = createRuntimeInstance(config.instanceId);
|
|
2861
2904
|
try {
|
|
2862
2905
|
const resources = createRuntimeResources({
|
|
2863
2906
|
definitions: config.server.resources ?? {},
|
|
2907
|
+
instance: instance.context,
|
|
2864
2908
|
lifecycle
|
|
2865
2909
|
});
|
|
2866
2910
|
const context = resources.context;
|
|
@@ -2876,14 +2920,17 @@ var createRuntime = async ({ config, debug = false, notifications = { send: asyn
|
|
|
2876
2920
|
});
|
|
2877
2921
|
lifecycle.signal.throwIfAborted();
|
|
2878
2922
|
lifecycle.completePreparation();
|
|
2923
|
+
const manifest = {
|
|
2924
|
+
debug,
|
|
2925
|
+
operations: [...operations.names],
|
|
2926
|
+
protocolVersion: 10,
|
|
2927
|
+
resources: [...resources.names],
|
|
2928
|
+
streams: [...streams.names]
|
|
2929
|
+
};
|
|
2879
2930
|
return {
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
protocolVersion: 9,
|
|
2884
|
-
resources: [...resources.names],
|
|
2885
|
-
streams: [...streams.names]
|
|
2886
|
-
},
|
|
2931
|
+
instance: instance.context,
|
|
2932
|
+
establishInstance: instance.establish,
|
|
2933
|
+
manifest,
|
|
2887
2934
|
dispose: lifecycle.dispose,
|
|
2888
2935
|
getOperation: operations.get,
|
|
2889
2936
|
getResource: resources.get,
|
|
@@ -3529,7 +3576,7 @@ var downloadVerifiedAsset = async ({ asset, destination, expectedSha256, fetch =
|
|
|
3529
3576
|
//#region src/internal/cli/commands/desktop-installer.ts
|
|
3530
3577
|
var bundleIdentifier = "com.overmux.desktop";
|
|
3531
3578
|
var bundleName = "Overmux.app";
|
|
3532
|
-
var runCommand = (command, args) => {
|
|
3579
|
+
var runCommand$1 = (command, args) => {
|
|
3533
3580
|
const result = spawnSync(command, args, { encoding: "utf8" });
|
|
3534
3581
|
if (result.error) throw new Error(`Could not run ${command}`, { cause: result.error });
|
|
3535
3582
|
return {
|
|
@@ -3565,7 +3612,7 @@ var createDependencies = (process) => ({
|
|
|
3565
3612
|
findRelease: findDesktopRelease,
|
|
3566
3613
|
homeDirectory: homedir(),
|
|
3567
3614
|
platform: process.platform,
|
|
3568
|
-
runCommand,
|
|
3615
|
+
runCommand: runCommand$1,
|
|
3569
3616
|
sleep,
|
|
3570
3617
|
stderr: process.stderr,
|
|
3571
3618
|
stdout: process.stdout
|
|
@@ -3814,6 +3861,368 @@ var createDocsCommand = ({ docsRoot, output }) => buildCommand({
|
|
|
3814
3861
|
docs: { brief: "Print the installed documentation directory" }
|
|
3815
3862
|
});
|
|
3816
3863
|
//#endregion
|
|
3864
|
+
//#region src/internal/cli/commands/init-template.ts
|
|
3865
|
+
var initScaffoldPaths = [
|
|
3866
|
+
".gitignore",
|
|
3867
|
+
"AGENTS.md",
|
|
3868
|
+
"CLAUDE.md",
|
|
3869
|
+
"mise.toml",
|
|
3870
|
+
"package.json",
|
|
3871
|
+
"pnpm-lock.yaml",
|
|
3872
|
+
"overmux.config.ts",
|
|
3873
|
+
"src/server/index.ts",
|
|
3874
|
+
"src/ui/app.tsx",
|
|
3875
|
+
"src/ui/index.html",
|
|
3876
|
+
"src/ui/main.tsx",
|
|
3877
|
+
"src/ui/styles.css",
|
|
3878
|
+
"vite.config.ts"
|
|
3879
|
+
];
|
|
3880
|
+
var packageJson = (overmuxVersion) => `${JSON.stringify({
|
|
3881
|
+
name: "my-overmux",
|
|
3882
|
+
private: true,
|
|
3883
|
+
type: "module",
|
|
3884
|
+
scripts: {
|
|
3885
|
+
build: "vite build",
|
|
3886
|
+
check: "overmux check --config ./overmux.config.ts",
|
|
3887
|
+
dev: "overmux serve --config ./overmux.config.ts"
|
|
3888
|
+
},
|
|
3889
|
+
dependencies: {
|
|
3890
|
+
overmux: overmuxVersion,
|
|
3891
|
+
react: "^19.0.0",
|
|
3892
|
+
"react-dom": "^19.0.0"
|
|
3893
|
+
},
|
|
3894
|
+
devDependencies: {
|
|
3895
|
+
"@types/react": "^19.0.0",
|
|
3896
|
+
"@types/react-dom": "^19.0.0",
|
|
3897
|
+
"@vitejs/plugin-react": "^6.0.0",
|
|
3898
|
+
typescript: "^5.9.0",
|
|
3899
|
+
vite: "^8.0.0"
|
|
3900
|
+
}
|
|
3901
|
+
}, null, 2)}\n`;
|
|
3902
|
+
var createInitScaffold = ({ overmuxVersion, toolchain }) => ({
|
|
3903
|
+
".gitignore": "node_modules\ndist\n",
|
|
3904
|
+
"AGENTS.md": "Immediately run `overmux ai context` for documentation about Overmux.\n",
|
|
3905
|
+
"CLAUDE.md": "@AGENTS.md\n",
|
|
3906
|
+
...toolchain === "mise" ? { "mise.toml": `[tools]
|
|
3907
|
+
node = "22"
|
|
3908
|
+
pnpm = "10"
|
|
3909
|
+
"npm:overmux" = "${overmuxVersion}"
|
|
3910
|
+
` } : {},
|
|
3911
|
+
"package.json": packageJson(overmuxVersion),
|
|
3912
|
+
"overmux.config.ts": `import { defineOvermuxConfig } from "overmux";
|
|
3913
|
+
|
|
3914
|
+
import server from "./src/server/index";
|
|
3915
|
+
|
|
3916
|
+
export default defineOvermuxConfig({
|
|
3917
|
+
auth: { mode: "cli-login" },
|
|
3918
|
+
productionWebAssetsDir: "./dist",
|
|
3919
|
+
server,
|
|
3920
|
+
vite: "./vite.config.ts",
|
|
3921
|
+
});
|
|
3922
|
+
`,
|
|
3923
|
+
"src/server/index.ts": `import { defineOvermuxServer } from "overmux";
|
|
3924
|
+
|
|
3925
|
+
export default defineOvermuxServer({ resources: {} });
|
|
3926
|
+
`,
|
|
3927
|
+
"src/ui/app.tsx": `import { defineOvermuxClient } from "overmux/client";
|
|
3928
|
+
|
|
3929
|
+
const App = () => <main>Overmux is running.</main>;
|
|
3930
|
+
|
|
3931
|
+
export default defineOvermuxClient({
|
|
3932
|
+
commands: {},
|
|
3933
|
+
component: App,
|
|
3934
|
+
});
|
|
3935
|
+
`,
|
|
3936
|
+
"src/ui/index.html": `<!doctype html>
|
|
3937
|
+
<html lang="en">
|
|
3938
|
+
<head>
|
|
3939
|
+
<meta charset="UTF-8" />
|
|
3940
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
3941
|
+
<title>Overmux</title>
|
|
3942
|
+
</head>
|
|
3943
|
+
<body>
|
|
3944
|
+
<div id="root">
|
|
3945
|
+
<p>Loading Overmux…</p>
|
|
3946
|
+
<button type="button" onclick="location.reload()">Retry</button>
|
|
3947
|
+
</div>
|
|
3948
|
+
<script type="module" src="/main.tsx"><\/script>
|
|
3949
|
+
</body>
|
|
3950
|
+
</html>
|
|
3951
|
+
`,
|
|
3952
|
+
"src/ui/main.tsx": `import { OvermuxHost } from "overmux/client";
|
|
3953
|
+
import { createRoot } from "react-dom/client";
|
|
3954
|
+
|
|
3955
|
+
import definition from "./app";
|
|
3956
|
+
import "./styles.css";
|
|
3957
|
+
|
|
3958
|
+
const root = document.querySelector("#root");
|
|
3959
|
+
if (!root) {
|
|
3960
|
+
throw new Error("Missing root element");
|
|
3961
|
+
}
|
|
3962
|
+
|
|
3963
|
+
createRoot(root).render(<OvermuxHost definition={definition} />);
|
|
3964
|
+
`,
|
|
3965
|
+
"src/ui/styles.css": `:root {
|
|
3966
|
+
color: #f5f5f5;
|
|
3967
|
+
background: #111;
|
|
3968
|
+
font-family: system-ui, sans-serif;
|
|
3969
|
+
}
|
|
3970
|
+
|
|
3971
|
+
body {
|
|
3972
|
+
margin: 0;
|
|
3973
|
+
}
|
|
3974
|
+
|
|
3975
|
+
main {
|
|
3976
|
+
display: grid;
|
|
3977
|
+
min-height: 100vh;
|
|
3978
|
+
place-items: center;
|
|
3979
|
+
}
|
|
3980
|
+
`,
|
|
3981
|
+
"vite.config.ts": `import viteReact from "@vitejs/plugin-react";
|
|
3982
|
+
import { defineConfig } from "vite";
|
|
3983
|
+
|
|
3984
|
+
export default defineConfig({
|
|
3985
|
+
build: { emptyOutDir: true, outDir: "../../dist" },
|
|
3986
|
+
plugins: [viteReact()],
|
|
3987
|
+
root: "src/ui",
|
|
3988
|
+
});
|
|
3989
|
+
`
|
|
3990
|
+
});
|
|
3991
|
+
//#endregion
|
|
3992
|
+
//#region src/internal/cli/commands/init.ts
|
|
3993
|
+
var miseActivationDocs = "https://mise.jdx.dev/getting-started.html#activate-mise";
|
|
3994
|
+
var runCommand = (command, args, options) => {
|
|
3995
|
+
const result = spawnSync(command, args, {
|
|
3996
|
+
cwd: options?.cwd,
|
|
3997
|
+
encoding: "utf8",
|
|
3998
|
+
maxBuffer: 20971520
|
|
3999
|
+
});
|
|
4000
|
+
return {
|
|
4001
|
+
error: result.error,
|
|
4002
|
+
status: result.status,
|
|
4003
|
+
stderr: result.stderr ?? "",
|
|
4004
|
+
stdout: result.stdout ?? ""
|
|
4005
|
+
};
|
|
4006
|
+
};
|
|
4007
|
+
var getLatestOvermuxVersion = async () => {
|
|
4008
|
+
const response = await fetch("https://registry.npmjs.org/overmux/latest", { headers: { accept: "application/json" } });
|
|
4009
|
+
if (!response.ok) throw new Error(`Could not resolve the latest Overmux version: npm returned ${response.status}`);
|
|
4010
|
+
const body = await response.json();
|
|
4011
|
+
const version = typeof body === "object" && body !== null && "version" in body ? body.version : void 0;
|
|
4012
|
+
if (typeof version !== "string") throw new Error("Could not resolve the latest Overmux version from npm");
|
|
4013
|
+
return version;
|
|
4014
|
+
};
|
|
4015
|
+
var commandExists = (result) => result.error?.code !== "ENOENT";
|
|
4016
|
+
var isMiseActivated = (dependencies) => {
|
|
4017
|
+
const doctor = dependencies.runCommand("mise", ["doctor", "--json"]);
|
|
4018
|
+
if (doctor.status !== 0) return false;
|
|
4019
|
+
try {
|
|
4020
|
+
const report = JSON.parse(doctor.stdout);
|
|
4021
|
+
return typeof report === "object" && report !== null && "activated" in report && report.activated === true;
|
|
4022
|
+
} catch {
|
|
4023
|
+
return false;
|
|
4024
|
+
}
|
|
4025
|
+
};
|
|
4026
|
+
var detectToolchain = (dependencies) => {
|
|
4027
|
+
const mise = dependencies.runCommand("mise", ["--version"]);
|
|
4028
|
+
if (commandExists(mise)) {
|
|
4029
|
+
if (mise.status !== 0) throw new Error(`Mise could not be validated. Activate mise and try again. ${miseActivationDocs}`);
|
|
4030
|
+
if (!isMiseActivated(dependencies)) throw new Error(`Mise must be activated in your shell before running overmux init. ${miseActivationDocs}`);
|
|
4031
|
+
return "mise";
|
|
4032
|
+
}
|
|
4033
|
+
const pnpm = dependencies.runCommand("pnpm", ["--version"]);
|
|
4034
|
+
const major = Number.parseInt(pnpm.stdout.trim().split(".")[0] ?? "", 10);
|
|
4035
|
+
if (!commandExists(pnpm) || pnpm.status !== 0 || !Number.isFinite(major)) throw new Error("pnpm 10 or newer is required when mise is not installed");
|
|
4036
|
+
if (major < 10) throw new Error(`pnpm 10 or newer is required when mise is not installed (found ${pnpm.stdout.trim()})`);
|
|
4037
|
+
return "pnpm";
|
|
4038
|
+
};
|
|
4039
|
+
var findCollisions = (directory) => {
|
|
4040
|
+
if (existsSync(directory) && !statSync(directory).isDirectory()) return [directory];
|
|
4041
|
+
return initScaffoldPaths.filter((path) => existsSync(join(directory, path)));
|
|
4042
|
+
};
|
|
4043
|
+
var writeScaffold = (directory, files) => {
|
|
4044
|
+
Object.entries(files).forEach(([path, content]) => {
|
|
4045
|
+
const destination = join(directory, path);
|
|
4046
|
+
mkdirSync(dirname(destination), { recursive: true });
|
|
4047
|
+
writeFileSync(destination, content);
|
|
4048
|
+
});
|
|
4049
|
+
};
|
|
4050
|
+
var runProjectCommand = ({ args, command, cwd, dependencies }) => {
|
|
4051
|
+
const result = dependencies.runCommand(command, args, { cwd });
|
|
4052
|
+
dependencies.stdout.write(result.stdout);
|
|
4053
|
+
dependencies.stderr.write(result.stderr);
|
|
4054
|
+
if (result.error || result.status !== 0) throw new Error(`Command failed: ${command} ${args.join(" ")}`);
|
|
4055
|
+
};
|
|
4056
|
+
var pnpmCommands = [["install", "--ignore-workspace"], [
|
|
4057
|
+
"exec",
|
|
4058
|
+
"overmux",
|
|
4059
|
+
"check",
|
|
4060
|
+
"--config",
|
|
4061
|
+
"./overmux.config.ts"
|
|
4062
|
+
]];
|
|
4063
|
+
var installAndCheck = ({ directory, dependencies, toolchain }) => {
|
|
4064
|
+
const context = {
|
|
4065
|
+
cwd: directory,
|
|
4066
|
+
dependencies
|
|
4067
|
+
};
|
|
4068
|
+
if (toolchain === "mise") runProjectCommand({
|
|
4069
|
+
...context,
|
|
4070
|
+
command: "mise",
|
|
4071
|
+
args: [
|
|
4072
|
+
"install",
|
|
4073
|
+
"node@22",
|
|
4074
|
+
"pnpm@10",
|
|
4075
|
+
"--yes"
|
|
4076
|
+
]
|
|
4077
|
+
});
|
|
4078
|
+
pnpmCommands.forEach((args) => runProjectCommand({
|
|
4079
|
+
...context,
|
|
4080
|
+
command: toolchain,
|
|
4081
|
+
args: toolchain === "mise" ? [
|
|
4082
|
+
"exec",
|
|
4083
|
+
"node@22",
|
|
4084
|
+
"pnpm@10",
|
|
4085
|
+
"--",
|
|
4086
|
+
"pnpm",
|
|
4087
|
+
...args
|
|
4088
|
+
] : args
|
|
4089
|
+
}));
|
|
4090
|
+
};
|
|
4091
|
+
var mergeScaffold = (source, target) => {
|
|
4092
|
+
if (!existsSync(target)) {
|
|
4093
|
+
renameSync(source, target);
|
|
4094
|
+
return;
|
|
4095
|
+
}
|
|
4096
|
+
cpSync(source, target, {
|
|
4097
|
+
errorOnExist: true,
|
|
4098
|
+
force: false,
|
|
4099
|
+
recursive: true
|
|
4100
|
+
});
|
|
4101
|
+
};
|
|
4102
|
+
var initializeOvermux = async (dependencies) => {
|
|
4103
|
+
const directory = resolve(dependencies.directory);
|
|
4104
|
+
const collisions = findCollisions(directory);
|
|
4105
|
+
if (collisions.length > 0) throw new Error(`Refusing to overwrite existing files:\n${collisions.map((path) => `- ${path}`).join("\n")}`);
|
|
4106
|
+
const toolchain = detectToolchain(dependencies);
|
|
4107
|
+
const files = createInitScaffold({
|
|
4108
|
+
overmuxVersion: await dependencies.getLatestOvermuxVersion(),
|
|
4109
|
+
toolchain
|
|
4110
|
+
});
|
|
4111
|
+
const parent = dirname(directory);
|
|
4112
|
+
mkdirSync(parent, { recursive: true });
|
|
4113
|
+
const stagingDirectory = mkdtempSync(join(parent, ".overmux-init-"));
|
|
4114
|
+
try {
|
|
4115
|
+
writeScaffold(stagingDirectory, Object.fromEntries(Object.entries(files).filter(([path]) => path !== "mise.toml")));
|
|
4116
|
+
installAndCheck({
|
|
4117
|
+
directory: stagingDirectory,
|
|
4118
|
+
dependencies,
|
|
4119
|
+
toolchain
|
|
4120
|
+
});
|
|
4121
|
+
if (!existsSync(join(stagingDirectory, "pnpm-lock.yaml"))) throw new Error("pnpm install did not generate pnpm-lock.yaml");
|
|
4122
|
+
if (files["mise.toml"]) writeFileSync(join(stagingDirectory, "mise.toml"), files["mise.toml"]);
|
|
4123
|
+
mergeScaffold(stagingDirectory, directory);
|
|
4124
|
+
} finally {
|
|
4125
|
+
rmSync(stagingDirectory, {
|
|
4126
|
+
force: true,
|
|
4127
|
+
recursive: true
|
|
4128
|
+
});
|
|
4129
|
+
}
|
|
4130
|
+
dependencies.stdout.write(`Initialized Overmux in ${directory}\nNext: overmux serve\n`);
|
|
4131
|
+
};
|
|
4132
|
+
var createInitCommand = (process) => buildCommand({
|
|
4133
|
+
func: () => initializeOvermux({
|
|
4134
|
+
directory: getOvermuxPaths({ environment: process.env }).configDir,
|
|
4135
|
+
getLatestOvermuxVersion,
|
|
4136
|
+
runCommand,
|
|
4137
|
+
stderr: process.stderr,
|
|
4138
|
+
stdout: process.stdout
|
|
4139
|
+
}),
|
|
4140
|
+
parameters: { flags: {} },
|
|
4141
|
+
docs: { brief: "Create a minimal Overmux application" }
|
|
4142
|
+
});
|
|
4143
|
+
//#endregion
|
|
4144
|
+
//#region src/internal/cli/commands/zellij-install.ts
|
|
4145
|
+
var resolveZellijInstall = (cwd) => {
|
|
4146
|
+
const projectUrl = pathToFileURL(resolve(cwd, "package.json"));
|
|
4147
|
+
const packagePath = findPackageJSON("@overmux/zellij/install", projectUrl);
|
|
4148
|
+
if (packagePath === void 0) throw new Error("package not found");
|
|
4149
|
+
const installExport = JSON.parse(readFileSync(packagePath, "utf8")).exports?.["./install"]?.import;
|
|
4150
|
+
if (typeof installExport !== "string") throw new Error("package has no importable ./install export");
|
|
4151
|
+
return resolve(dirname(packagePath), installExport);
|
|
4152
|
+
};
|
|
4153
|
+
var defaultDependencies = () => {
|
|
4154
|
+
const cwd = process.cwd();
|
|
4155
|
+
return {
|
|
4156
|
+
cwd,
|
|
4157
|
+
importModule: (specifier) => import(specifier),
|
|
4158
|
+
resolveInstall: () => resolveZellijInstall(cwd)
|
|
4159
|
+
};
|
|
4160
|
+
};
|
|
4161
|
+
var executeZellijInstall = async ({ session }, dependencies = defaultDependencies()) => {
|
|
4162
|
+
let modulePath;
|
|
4163
|
+
try {
|
|
4164
|
+
modulePath = dependencies.resolveInstall();
|
|
4165
|
+
} catch {
|
|
4166
|
+
throw new Error(`Could not resolve @overmux/zellij/install from ${dependencies.cwd}. Add @overmux/zellij to this project, then run the command again.`);
|
|
4167
|
+
}
|
|
4168
|
+
const integration = await dependencies.importModule(pathToFileURL(modulePath).href);
|
|
4169
|
+
if (typeof integration.installZellij !== "function") throw new Error("@overmux/zellij/install does not export installZellij. Update @overmux/zellij and run the command again.");
|
|
4170
|
+
return integration.installZellij({ session });
|
|
4171
|
+
};
|
|
4172
|
+
var runZellijInstall = async ({ session }) => {
|
|
4173
|
+
const result = await executeZellijInstall({ session });
|
|
4174
|
+
console.log(`Installed Zellij plugin ${result.pluginVersion} (protocol ${result.protocolVersion})\nSession: ${result.session}\nArtifact: ${result.artifactPath}\nSHA-256: ${result.sha256}`);
|
|
4175
|
+
};
|
|
4176
|
+
var integrationCommand = buildRouteMap({
|
|
4177
|
+
docs: { brief: "Manage Overmux integrations" },
|
|
4178
|
+
routes: { install: buildRouteMap({
|
|
4179
|
+
docs: { brief: "Install an Overmux integration" },
|
|
4180
|
+
routes: { zellij: buildCommand({
|
|
4181
|
+
docs: { brief: "Install and approve the @overmux/zellij plugin" },
|
|
4182
|
+
func: runZellijInstall,
|
|
4183
|
+
parameters: { flags: { session: {
|
|
4184
|
+
brief: "Target an active Zellij session",
|
|
4185
|
+
kind: "parsed",
|
|
4186
|
+
optional: true,
|
|
4187
|
+
parse: String,
|
|
4188
|
+
placeholder: "name"
|
|
4189
|
+
} } }
|
|
4190
|
+
}) }
|
|
4191
|
+
}) }
|
|
4192
|
+
});
|
|
4193
|
+
//#endregion
|
|
4194
|
+
//#region src/internal/cli/commands/instance.ts
|
|
4195
|
+
var runInstance = async (flags, output) => {
|
|
4196
|
+
const port = flags.port === void 0 ? void 0 : parsePort(flags.port);
|
|
4197
|
+
if (port instanceof Error) throw port;
|
|
4198
|
+
const identity = createInstanceIdentity((await sendControlRequest(await discoverInstance(port), { type: "get-instance" })).instanceId);
|
|
4199
|
+
output.write(flags.json ? `${JSON.stringify(identity)}\n` : `Instance ID: ${identity.instanceId}\nDeep-link prefix: ${identity.deepLinkPrefix}\n`);
|
|
4200
|
+
};
|
|
4201
|
+
var createInstanceCommand = (output) => buildCommand({
|
|
4202
|
+
func: (flags) => runInstance(flags, output),
|
|
4203
|
+
parameters: {
|
|
4204
|
+
aliases: { p: "port" },
|
|
4205
|
+
flags: {
|
|
4206
|
+
json: {
|
|
4207
|
+
brief: "Print machine-readable JSON",
|
|
4208
|
+
kind: "boolean",
|
|
4209
|
+
optional: true
|
|
4210
|
+
},
|
|
4211
|
+
port: {
|
|
4212
|
+
brief: "Running local server port",
|
|
4213
|
+
kind: "parsed",
|
|
4214
|
+
optional: true,
|
|
4215
|
+
parse: String
|
|
4216
|
+
}
|
|
4217
|
+
},
|
|
4218
|
+
positional: {
|
|
4219
|
+
kind: "tuple",
|
|
4220
|
+
parameters: []
|
|
4221
|
+
}
|
|
4222
|
+
},
|
|
4223
|
+
docs: { brief: "Print the identity of a running Overmux server" }
|
|
4224
|
+
});
|
|
4225
|
+
//#endregion
|
|
3817
4226
|
//#region src/internal/shared/routes.ts
|
|
3818
4227
|
var viteHmrPath = "/_overmux/vite/hmr";
|
|
3819
4228
|
//#endregion
|
|
@@ -4721,7 +5130,7 @@ var detectCliEnvironment = async (process = globalThis.process) => {
|
|
|
4721
5130
|
//#endregion
|
|
4722
5131
|
//#region src/internal/cli/app.ts
|
|
4723
5132
|
var createCliApp = (process = globalThis.process) => buildApplication(buildRouteMap({
|
|
4724
|
-
docs: { brief: "
|
|
5133
|
+
docs: { brief: "Initialize and manage Overmux applications" },
|
|
4725
5134
|
routes: {
|
|
4726
5135
|
ai: createAiRoute(process),
|
|
4727
5136
|
auth: authRoute,
|
|
@@ -4732,6 +5141,9 @@ var createCliApp = (process = globalThis.process) => buildApplication(buildRoute
|
|
|
4732
5141
|
docsRoot: resolveInstalledDocsRoot(import.meta.url),
|
|
4733
5142
|
output: process.stdout
|
|
4734
5143
|
}),
|
|
5144
|
+
init: createInitCommand(process),
|
|
5145
|
+
integration: integrationCommand,
|
|
5146
|
+
instance: createInstanceCommand(process.stdout),
|
|
4735
5147
|
serve: serveCommand
|
|
4736
5148
|
}
|
|
4737
5149
|
}), {
|